2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
146 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
148 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
149 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
150 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
159 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
160 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
161 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
162 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
163 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
164 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
166 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
167 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
168 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
169 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
171 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
172 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
173 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
174 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
175 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
176 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
177 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
179 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
180 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
181 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
182 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
183 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
184 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
185 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
186 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
188 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
190 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
192 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
194 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
196 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
197 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
198 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
199 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
200 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
201 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
202 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
203 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
204 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
206 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
207 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
209 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
211 extern cvar_t v_glslgamma;
213 extern qboolean v_flipped_state;
215 static struct r_bloomstate_s
220 int bloomwidth, bloomheight;
222 int screentexturewidth, screentextureheight;
223 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
225 int bloomtexturewidth, bloomtextureheight;
226 rtexture_t *texture_bloom;
228 // arrays for rendering the screen passes
229 float screentexcoord2f[8];
230 float bloomtexcoord2f[8];
231 float offsettexcoord2f[8];
233 r_viewport_t viewport;
237 r_waterstate_t r_waterstate;
239 /// shadow volume bsp struct with automatically growing nodes buffer
242 rtexture_t *r_texture_blanknormalmap;
243 rtexture_t *r_texture_white;
244 rtexture_t *r_texture_grey128;
245 rtexture_t *r_texture_black;
246 rtexture_t *r_texture_notexture;
247 rtexture_t *r_texture_whitecube;
248 rtexture_t *r_texture_normalizationcube;
249 rtexture_t *r_texture_fogattenuation;
250 rtexture_t *r_texture_fogheighttexture;
251 rtexture_t *r_texture_gammaramps;
252 unsigned int r_texture_gammaramps_serial;
253 //rtexture_t *r_texture_fogintensity;
254 rtexture_t *r_texture_reflectcube;
256 // TODO: hash lookups?
257 typedef struct cubemapinfo_s
264 int r_texture_numcubemaps;
265 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
267 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
268 unsigned int r_numqueries;
269 unsigned int r_maxqueries;
271 typedef struct r_qwskincache_s
273 char name[MAX_QPATH];
274 skinframe_t *skinframe;
278 static r_qwskincache_t *r_qwskincache;
279 static int r_qwskincache_size;
281 /// vertex coordinates for a quad that covers the screen exactly
282 extern const float r_screenvertex3f[12];
283 extern const float r_d3dscreenvertex3f[12];
284 const float r_screenvertex3f[12] =
291 const float r_d3dscreenvertex3f[12] =
299 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
302 for (i = 0;i < verts;i++)
313 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
316 for (i = 0;i < verts;i++)
326 // FIXME: move this to client?
329 if (gamemode == GAME_NEHAHRA)
331 Cvar_Set("gl_fogenable", "0");
332 Cvar_Set("gl_fogdensity", "0.2");
333 Cvar_Set("gl_fogred", "0.3");
334 Cvar_Set("gl_foggreen", "0.3");
335 Cvar_Set("gl_fogblue", "0.3");
337 r_refdef.fog_density = 0;
338 r_refdef.fog_red = 0;
339 r_refdef.fog_green = 0;
340 r_refdef.fog_blue = 0;
341 r_refdef.fog_alpha = 1;
342 r_refdef.fog_start = 0;
343 r_refdef.fog_end = 16384;
344 r_refdef.fog_height = 1<<30;
345 r_refdef.fog_fadedepth = 128;
346 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
349 static void R_BuildBlankTextures(void)
351 unsigned char data[4];
352 data[2] = 128; // normal X
353 data[1] = 128; // normal Y
354 data[0] = 255; // normal Z
355 data[3] = 128; // height
356 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 static void R_BuildNoTexture(void)
377 unsigned char pix[16][16][4];
378 // this makes a light grey/dark grey checkerboard texture
379 for (y = 0;y < 16;y++)
381 for (x = 0;x < 16;x++)
383 if ((y < 8) ^ (x < 8))
399 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
402 static void R_BuildWhiteCube(void)
404 unsigned char data[6*1*1*4];
405 memset(data, 255, sizeof(data));
406 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
409 static void R_BuildNormalizationCube(void)
413 vec_t s, t, intensity;
416 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
417 for (side = 0;side < 6;side++)
419 for (y = 0;y < NORMSIZE;y++)
421 for (x = 0;x < NORMSIZE;x++)
423 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459 intensity = 127.0f / sqrt(DotProduct(v, v));
460 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
461 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
462 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
463 data[((side*64+y)*64+x)*4+3] = 255;
467 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
471 static void R_BuildFogTexture(void)
475 unsigned char data1[FOGWIDTH][4];
476 //unsigned char data2[FOGWIDTH][4];
479 r_refdef.fogmasktable_start = r_refdef.fog_start;
480 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
481 r_refdef.fogmasktable_range = r_refdef.fogrange;
482 r_refdef.fogmasktable_density = r_refdef.fog_density;
484 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
485 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
487 d = (x * r - r_refdef.fogmasktable_start);
488 if(developer_extra.integer)
489 Con_DPrintf("%f ", d);
491 if (r_fog_exp2.integer)
492 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
494 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
495 if(developer_extra.integer)
496 Con_DPrintf(" : %f ", alpha);
497 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
498 if(developer_extra.integer)
499 Con_DPrintf(" = %f\n", alpha);
500 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
503 for (x = 0;x < FOGWIDTH;x++)
505 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
510 //data2[x][0] = 255 - b;
511 //data2[x][1] = 255 - b;
512 //data2[x][2] = 255 - b;
515 if (r_texture_fogattenuation)
517 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
522 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
523 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
527 static void R_BuildFogHeightTexture(void)
529 unsigned char *inpixels;
537 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
538 if (r_refdef.fogheighttexturename[0])
539 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
542 r_refdef.fog_height_tablesize = 0;
543 if (r_texture_fogheighttexture)
544 R_FreeTexture(r_texture_fogheighttexture);
545 r_texture_fogheighttexture = NULL;
546 if (r_refdef.fog_height_table2d)
547 Mem_Free(r_refdef.fog_height_table2d);
548 r_refdef.fog_height_table2d = NULL;
549 if (r_refdef.fog_height_table1d)
550 Mem_Free(r_refdef.fog_height_table1d);
551 r_refdef.fog_height_table1d = NULL;
555 r_refdef.fog_height_tablesize = size;
556 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
557 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
558 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
560 // LordHavoc: now the magic - what is that table2d for? it is a cooked
561 // average fog color table accounting for every fog layer between a point
562 // and the camera. (Note: attenuation is handled separately!)
563 for (y = 0;y < size;y++)
565 for (x = 0;x < size;x++)
571 for (j = x;j <= y;j++)
573 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
579 for (j = x;j >= y;j--)
581 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
586 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
588 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
589 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
592 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
595 //=======================================================================================================================================================
597 static const char *builtinshaderstring =
598 #include "shader_glsl.h"
601 const char *builtinhlslshaderstring =
602 #include "shader_hlsl.h"
605 char *glslshaderstring = NULL;
606 char *hlslshaderstring = NULL;
608 //=======================================================================================================================================================
610 typedef struct shaderpermutationinfo_s
615 shaderpermutationinfo_t;
617 typedef struct shadermodeinfo_s
619 const char *vertexfilename;
620 const char *geometryfilename;
621 const char *fragmentfilename;
627 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
628 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
630 {"#define USEDIFFUSE\n", " diffuse"},
631 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
632 {"#define USEVIEWTINT\n", " viewtint"},
633 {"#define USECOLORMAPPING\n", " colormapping"},
634 {"#define USESATURATION\n", " saturation"},
635 {"#define USEFOGINSIDE\n", " foginside"},
636 {"#define USEFOGOUTSIDE\n", " fogoutside"},
637 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
638 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
639 {"#define USEGAMMARAMPS\n", " gammaramps"},
640 {"#define USECUBEFILTER\n", " cubefilter"},
641 {"#define USEGLOW\n", " glow"},
642 {"#define USEBLOOM\n", " bloom"},
643 {"#define USESPECULAR\n", " specular"},
644 {"#define USEPOSTPROCESSING\n", " postprocessing"},
645 {"#define USEREFLECTION\n", " reflection"},
646 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
647 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
648 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
649 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
650 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
651 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
652 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
653 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
654 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
655 {"#define USEALPHAKILL\n", " alphakill"},
656 {"#define USEREFLECTCUBE\n", " reflectcube"},
657 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
658 {"#define USEBOUNCEGRID\n", " bouncegrid"},
659 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
662 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
663 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
665 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
666 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
667 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
683 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
685 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
686 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 struct r_glsl_permutation_s;
704 typedef struct r_glsl_permutation_s
707 struct r_glsl_permutation_s *hashnext;
709 unsigned int permutation;
711 /// indicates if we have tried compiling this permutation already
713 /// 0 if compilation failed
715 // texture units assigned to each detected uniform
716 int tex_Texture_First;
717 int tex_Texture_Second;
718 int tex_Texture_GammaRamps;
719 int tex_Texture_Normal;
720 int tex_Texture_Color;
721 int tex_Texture_Gloss;
722 int tex_Texture_Glow;
723 int tex_Texture_SecondaryNormal;
724 int tex_Texture_SecondaryColor;
725 int tex_Texture_SecondaryGloss;
726 int tex_Texture_SecondaryGlow;
727 int tex_Texture_Pants;
728 int tex_Texture_Shirt;
729 int tex_Texture_FogHeightTexture;
730 int tex_Texture_FogMask;
731 int tex_Texture_Lightmap;
732 int tex_Texture_Deluxemap;
733 int tex_Texture_Attenuation;
734 int tex_Texture_Cube;
735 int tex_Texture_Refraction;
736 int tex_Texture_Reflection;
737 int tex_Texture_ShadowMap2D;
738 int tex_Texture_CubeProjection;
739 int tex_Texture_ScreenDepth;
740 int tex_Texture_ScreenNormalMap;
741 int tex_Texture_ScreenDiffuse;
742 int tex_Texture_ScreenSpecular;
743 int tex_Texture_ReflectMask;
744 int tex_Texture_ReflectCube;
745 int tex_Texture_BounceGrid;
746 /// locations of detected uniforms in program object, or -1 if not found
747 int loc_Texture_First;
748 int loc_Texture_Second;
749 int loc_Texture_GammaRamps;
750 int loc_Texture_Normal;
751 int loc_Texture_Color;
752 int loc_Texture_Gloss;
753 int loc_Texture_Glow;
754 int loc_Texture_SecondaryNormal;
755 int loc_Texture_SecondaryColor;
756 int loc_Texture_SecondaryGloss;
757 int loc_Texture_SecondaryGlow;
758 int loc_Texture_Pants;
759 int loc_Texture_Shirt;
760 int loc_Texture_FogHeightTexture;
761 int loc_Texture_FogMask;
762 int loc_Texture_Lightmap;
763 int loc_Texture_Deluxemap;
764 int loc_Texture_Attenuation;
765 int loc_Texture_Cube;
766 int loc_Texture_Refraction;
767 int loc_Texture_Reflection;
768 int loc_Texture_ShadowMap2D;
769 int loc_Texture_CubeProjection;
770 int loc_Texture_ScreenDepth;
771 int loc_Texture_ScreenNormalMap;
772 int loc_Texture_ScreenDiffuse;
773 int loc_Texture_ScreenSpecular;
774 int loc_Texture_ReflectMask;
775 int loc_Texture_ReflectCube;
776 int loc_Texture_BounceGrid;
778 int loc_BloomBlur_Parameters;
780 int loc_Color_Ambient;
781 int loc_Color_Diffuse;
782 int loc_Color_Specular;
786 int loc_DeferredColor_Ambient;
787 int loc_DeferredColor_Diffuse;
788 int loc_DeferredColor_Specular;
789 int loc_DeferredMod_Diffuse;
790 int loc_DeferredMod_Specular;
791 int loc_DistortScaleRefractReflect;
794 int loc_FogHeightFade;
796 int loc_FogPlaneViewDist;
797 int loc_FogRangeRecip;
800 int loc_LightPosition;
801 int loc_OffsetMapping_ScaleSteps;
803 int loc_ReflectColor;
804 int loc_ReflectFactor;
805 int loc_ReflectOffset;
806 int loc_RefractColor;
808 int loc_ScreenCenterRefractReflect;
809 int loc_ScreenScaleRefractReflect;
810 int loc_ScreenToDepth;
811 int loc_ShadowMap_Parameters;
812 int loc_ShadowMap_TextureScale;
813 int loc_SpecularPower;
818 int loc_ViewTintColor;
820 int loc_ModelToLight;
822 int loc_BackgroundTexMatrix;
823 int loc_ModelViewProjectionMatrix;
824 int loc_ModelViewMatrix;
825 int loc_PixelToScreenTexCoord;
826 int loc_ModelToReflectCube;
827 int loc_ShadowMapMatrix;
828 int loc_BloomColorSubtract;
829 int loc_NormalmapScrollBlend;
830 int loc_BounceGridMatrix;
831 int loc_BounceGridIntensity;
833 r_glsl_permutation_t;
835 #define SHADERPERMUTATION_HASHSIZE 256
838 // non-degradable "lightweight" shader parameters to keep the permutations simpler
839 // these can NOT degrade! only use for simple stuff
842 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
843 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
844 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
845 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
846 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
847 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
849 #define SHADERSTATICPARMS_COUNT 6
851 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
852 static int shaderstaticparms_count = 0;
854 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
855 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
856 qboolean R_CompileShader_CheckStaticParms(void)
858 static int r_compileshader_staticparms_save[1];
859 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
860 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
863 if (r_glsl_saturation_redcompensate.integer)
864 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
865 if (r_shadow_glossexact.integer)
866 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
867 if (r_glsl_postprocess.integer)
869 if (r_glsl_postprocess_uservec1_enable.integer)
870 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
871 if (r_glsl_postprocess_uservec2_enable.integer)
872 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
873 if (r_glsl_postprocess_uservec3_enable.integer)
874 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
875 if (r_glsl_postprocess_uservec4_enable.integer)
876 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
878 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
881 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
882 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
883 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
885 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
886 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
888 shaderstaticparms_count = 0;
891 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
892 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
893 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
894 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
895 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
896 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
899 /// information about each possible shader permutation
900 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
901 /// currently selected permutation
902 r_glsl_permutation_t *r_glsl_permutation;
903 /// storage for permutations linked in the hash table
904 memexpandablearray_t r_glsl_permutationarray;
906 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
908 //unsigned int hashdepth = 0;
909 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
910 r_glsl_permutation_t *p;
911 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
913 if (p->mode == mode && p->permutation == permutation)
915 //if (hashdepth > 10)
916 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
921 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
923 p->permutation = permutation;
924 p->hashnext = r_glsl_permutationhash[mode][hashindex];
925 r_glsl_permutationhash[mode][hashindex] = p;
926 //if (hashdepth > 10)
927 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
931 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
934 if (!filename || !filename[0])
936 if (!strcmp(filename, "glsl/default.glsl"))
938 if (!glslshaderstring)
940 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
941 if (glslshaderstring)
942 Con_DPrintf("Loading shaders from file %s...\n", filename);
944 glslshaderstring = (char *)builtinshaderstring;
946 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
947 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
950 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
953 if (printfromdisknotice)
954 Con_DPrintf("from disk %s... ", filename);
960 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
964 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
965 char *vertexstring, *geometrystring, *fragmentstring;
966 char permutationname[256];
967 int vertstrings_count = 0;
968 int geomstrings_count = 0;
969 int fragstrings_count = 0;
970 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
971 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
972 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
979 permutationname[0] = 0;
980 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
981 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
982 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
984 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
986 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
987 if(vid.support.gl20shaders130)
989 vertstrings_list[vertstrings_count++] = "#version 130\n";
990 geomstrings_list[geomstrings_count++] = "#version 130\n";
991 fragstrings_list[fragstrings_count++] = "#version 130\n";
994 // the first pretext is which type of shader to compile as
995 // (later these will all be bound together as a program object)
996 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
997 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
998 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1000 // the second pretext is the mode (for example a light source)
1001 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1002 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1003 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1004 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1006 // now add all the permutation pretexts
1007 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1009 if (permutation & (1<<i))
1011 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1012 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1013 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1014 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1018 // keep line numbers correct
1019 vertstrings_list[vertstrings_count++] = "\n";
1020 geomstrings_list[geomstrings_count++] = "\n";
1021 fragstrings_list[fragstrings_count++] = "\n";
1026 R_CompileShader_AddStaticParms(mode, permutation);
1027 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1028 vertstrings_count += shaderstaticparms_count;
1029 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1030 geomstrings_count += shaderstaticparms_count;
1031 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1032 fragstrings_count += shaderstaticparms_count;
1034 // now append the shader text itself
1035 vertstrings_list[vertstrings_count++] = vertexstring;
1036 geomstrings_list[geomstrings_count++] = geometrystring;
1037 fragstrings_list[fragstrings_count++] = fragmentstring;
1039 // if any sources were NULL, clear the respective list
1041 vertstrings_count = 0;
1042 if (!geometrystring)
1043 geomstrings_count = 0;
1044 if (!fragmentstring)
1045 fragstrings_count = 0;
1047 // compile the shader program
1048 if (vertstrings_count + geomstrings_count + fragstrings_count)
1049 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1053 qglUseProgram(p->program);CHECKGLERROR
1054 // look up all the uniform variable names we care about, so we don't
1055 // have to look them up every time we set them
1057 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1058 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1059 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1060 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1061 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1062 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1063 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1064 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1065 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1066 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1067 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1068 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1069 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1070 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1071 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1072 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1073 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1074 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1075 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1076 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1077 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1078 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1079 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1080 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1081 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1082 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1083 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1084 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1085 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1086 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1087 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1088 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1089 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1090 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1091 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1092 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1093 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1094 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1095 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1096 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1097 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1098 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1099 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1100 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1101 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1102 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1103 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1104 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1105 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1106 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1107 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1108 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1109 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1110 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1111 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1112 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1113 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1114 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1115 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1116 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1117 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1118 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1119 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1120 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1121 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1122 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1123 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1124 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1125 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1126 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1127 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1128 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1129 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1130 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1131 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1132 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1133 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1134 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1135 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1136 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1137 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1138 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1139 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1140 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1141 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1142 // initialize the samplers to refer to the texture units we use
1143 p->tex_Texture_First = -1;
1144 p->tex_Texture_Second = -1;
1145 p->tex_Texture_GammaRamps = -1;
1146 p->tex_Texture_Normal = -1;
1147 p->tex_Texture_Color = -1;
1148 p->tex_Texture_Gloss = -1;
1149 p->tex_Texture_Glow = -1;
1150 p->tex_Texture_SecondaryNormal = -1;
1151 p->tex_Texture_SecondaryColor = -1;
1152 p->tex_Texture_SecondaryGloss = -1;
1153 p->tex_Texture_SecondaryGlow = -1;
1154 p->tex_Texture_Pants = -1;
1155 p->tex_Texture_Shirt = -1;
1156 p->tex_Texture_FogHeightTexture = -1;
1157 p->tex_Texture_FogMask = -1;
1158 p->tex_Texture_Lightmap = -1;
1159 p->tex_Texture_Deluxemap = -1;
1160 p->tex_Texture_Attenuation = -1;
1161 p->tex_Texture_Cube = -1;
1162 p->tex_Texture_Refraction = -1;
1163 p->tex_Texture_Reflection = -1;
1164 p->tex_Texture_ShadowMap2D = -1;
1165 p->tex_Texture_CubeProjection = -1;
1166 p->tex_Texture_ScreenDepth = -1;
1167 p->tex_Texture_ScreenNormalMap = -1;
1168 p->tex_Texture_ScreenDiffuse = -1;
1169 p->tex_Texture_ScreenSpecular = -1;
1170 p->tex_Texture_ReflectMask = -1;
1171 p->tex_Texture_ReflectCube = -1;
1172 p->tex_Texture_BounceGrid = -1;
1174 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1175 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1176 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1177 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1178 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1179 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1180 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1181 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1182 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1183 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1184 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1185 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1186 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1187 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1188 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1189 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1190 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1191 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1192 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1193 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1194 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1195 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1196 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1197 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1198 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1199 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1200 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1201 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1202 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1203 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1205 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1208 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1212 Mem_Free(vertexstring);
1214 Mem_Free(geometrystring);
1216 Mem_Free(fragmentstring);
1219 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1221 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1222 if (r_glsl_permutation != perm)
1224 r_glsl_permutation = perm;
1225 if (!r_glsl_permutation->program)
1227 if (!r_glsl_permutation->compiled)
1228 R_GLSL_CompilePermutation(perm, mode, permutation);
1229 if (!r_glsl_permutation->program)
1231 // remove features until we find a valid permutation
1233 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1235 // reduce i more quickly whenever it would not remove any bits
1236 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1237 if (!(permutation & j))
1240 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1241 if (!r_glsl_permutation->compiled)
1242 R_GLSL_CompilePermutation(perm, mode, permutation);
1243 if (r_glsl_permutation->program)
1246 if (i >= SHADERPERMUTATION_COUNT)
1248 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1249 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1250 qglUseProgram(0);CHECKGLERROR
1251 return; // no bit left to clear, entire mode is broken
1256 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1258 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1259 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1260 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1267 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1268 extern D3DCAPS9 vid_d3d9caps;
1271 struct r_hlsl_permutation_s;
1272 typedef struct r_hlsl_permutation_s
1274 /// hash lookup data
1275 struct r_hlsl_permutation_s *hashnext;
1277 unsigned int permutation;
1279 /// indicates if we have tried compiling this permutation already
1281 /// NULL if compilation failed
1282 IDirect3DVertexShader9 *vertexshader;
1283 IDirect3DPixelShader9 *pixelshader;
1285 r_hlsl_permutation_t;
1287 typedef enum D3DVSREGISTER_e
1289 D3DVSREGISTER_TexMatrix = 0, // float4x4
1290 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1291 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1292 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1293 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1294 D3DVSREGISTER_ModelToLight = 20, // float4x4
1295 D3DVSREGISTER_EyePosition = 24,
1296 D3DVSREGISTER_FogPlane = 25,
1297 D3DVSREGISTER_LightDir = 26,
1298 D3DVSREGISTER_LightPosition = 27,
1302 typedef enum D3DPSREGISTER_e
1304 D3DPSREGISTER_Alpha = 0,
1305 D3DPSREGISTER_BloomBlur_Parameters = 1,
1306 D3DPSREGISTER_ClientTime = 2,
1307 D3DPSREGISTER_Color_Ambient = 3,
1308 D3DPSREGISTER_Color_Diffuse = 4,
1309 D3DPSREGISTER_Color_Specular = 5,
1310 D3DPSREGISTER_Color_Glow = 6,
1311 D3DPSREGISTER_Color_Pants = 7,
1312 D3DPSREGISTER_Color_Shirt = 8,
1313 D3DPSREGISTER_DeferredColor_Ambient = 9,
1314 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1315 D3DPSREGISTER_DeferredColor_Specular = 11,
1316 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1317 D3DPSREGISTER_DeferredMod_Specular = 13,
1318 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1319 D3DPSREGISTER_EyePosition = 15, // unused
1320 D3DPSREGISTER_FogColor = 16,
1321 D3DPSREGISTER_FogHeightFade = 17,
1322 D3DPSREGISTER_FogPlane = 18,
1323 D3DPSREGISTER_FogPlaneViewDist = 19,
1324 D3DPSREGISTER_FogRangeRecip = 20,
1325 D3DPSREGISTER_LightColor = 21,
1326 D3DPSREGISTER_LightDir = 22, // unused
1327 D3DPSREGISTER_LightPosition = 23,
1328 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1329 D3DPSREGISTER_PixelSize = 25,
1330 D3DPSREGISTER_ReflectColor = 26,
1331 D3DPSREGISTER_ReflectFactor = 27,
1332 D3DPSREGISTER_ReflectOffset = 28,
1333 D3DPSREGISTER_RefractColor = 29,
1334 D3DPSREGISTER_Saturation = 30,
1335 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1336 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1337 D3DPSREGISTER_ScreenToDepth = 33,
1338 D3DPSREGISTER_ShadowMap_Parameters = 34,
1339 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1340 D3DPSREGISTER_SpecularPower = 36,
1341 D3DPSREGISTER_UserVec1 = 37,
1342 D3DPSREGISTER_UserVec2 = 38,
1343 D3DPSREGISTER_UserVec3 = 39,
1344 D3DPSREGISTER_UserVec4 = 40,
1345 D3DPSREGISTER_ViewTintColor = 41,
1346 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1347 D3DPSREGISTER_BloomColorSubtract = 43,
1348 D3DPSREGISTER_ViewToLight = 44, // float4x4
1349 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1350 D3DPSREGISTER_NormalmapScrollBlend = 52,
1355 /// information about each possible shader permutation
1356 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1357 /// currently selected permutation
1358 r_hlsl_permutation_t *r_hlsl_permutation;
1359 /// storage for permutations linked in the hash table
1360 memexpandablearray_t r_hlsl_permutationarray;
1362 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1364 //unsigned int hashdepth = 0;
1365 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1366 r_hlsl_permutation_t *p;
1367 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1369 if (p->mode == mode && p->permutation == permutation)
1371 //if (hashdepth > 10)
1372 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1377 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1379 p->permutation = permutation;
1380 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1381 r_hlsl_permutationhash[mode][hashindex] = p;
1382 //if (hashdepth > 10)
1383 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1387 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1390 if (!filename || !filename[0])
1392 if (!strcmp(filename, "hlsl/default.hlsl"))
1394 if (!hlslshaderstring)
1396 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1397 if (hlslshaderstring)
1398 Con_DPrintf("Loading shaders from file %s...\n", filename);
1400 hlslshaderstring = (char *)builtinhlslshaderstring;
1402 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1403 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1404 return shaderstring;
1406 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1409 if (printfromdisknotice)
1410 Con_DPrintf("from disk %s... ", filename);
1411 return shaderstring;
1413 return shaderstring;
1417 //#include <d3dx9shader.h>
1418 //#include <d3dx9mesh.h>
1420 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1422 DWORD *vsbin = NULL;
1423 DWORD *psbin = NULL;
1424 fs_offset_t vsbinsize;
1425 fs_offset_t psbinsize;
1426 // IDirect3DVertexShader9 *vs = NULL;
1427 // IDirect3DPixelShader9 *ps = NULL;
1428 ID3DXBuffer *vslog = NULL;
1429 ID3DXBuffer *vsbuffer = NULL;
1430 ID3DXConstantTable *vsconstanttable = NULL;
1431 ID3DXBuffer *pslog = NULL;
1432 ID3DXBuffer *psbuffer = NULL;
1433 ID3DXConstantTable *psconstanttable = NULL;
1436 char temp[MAX_INPUTLINE];
1437 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1438 qboolean debugshader = gl_paranoid.integer != 0;
1439 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1440 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1443 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1444 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1446 if ((!vsbin && vertstring) || (!psbin && fragstring))
1448 const char* dllnames_d3dx9 [] =
1472 dllhandle_t d3dx9_dll = NULL;
1473 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1474 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1475 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1476 dllfunction_t d3dx9_dllfuncs[] =
1478 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1479 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1480 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1483 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1485 DWORD shaderflags = 0;
1487 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1488 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1489 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1490 if (vertstring && vertstring[0])
1494 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1495 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1496 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1497 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1500 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1503 vsbinsize = vsbuffer->GetBufferSize();
1504 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1505 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1506 vsbuffer->Release();
1510 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1511 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1515 if (fragstring && fragstring[0])
1519 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1520 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1521 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1522 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1525 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1528 psbinsize = psbuffer->GetBufferSize();
1529 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1530 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1531 psbuffer->Release();
1535 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1536 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1540 Sys_UnloadLibrary(&d3dx9_dll);
1543 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1547 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1548 if (FAILED(vsresult))
1549 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1550 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1551 if (FAILED(psresult))
1552 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1554 // free the shader data
1555 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1556 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1559 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1562 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1563 int vertstring_length = 0;
1564 int geomstring_length = 0;
1565 int fragstring_length = 0;
1567 char *vertexstring, *geometrystring, *fragmentstring;
1568 char *vertstring, *geomstring, *fragstring;
1569 char permutationname[256];
1570 char cachename[256];
1571 int vertstrings_count = 0;
1572 int geomstrings_count = 0;
1573 int fragstrings_count = 0;
1574 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1575 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1576 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1581 p->vertexshader = NULL;
1582 p->pixelshader = NULL;
1584 permutationname[0] = 0;
1586 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1587 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1588 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1590 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1591 strlcat(cachename, "hlsl/", sizeof(cachename));
1593 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1594 vertstrings_count = 0;
1595 geomstrings_count = 0;
1596 fragstrings_count = 0;
1597 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1598 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1599 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1601 // the first pretext is which type of shader to compile as
1602 // (later these will all be bound together as a program object)
1603 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1604 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1605 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1607 // the second pretext is the mode (for example a light source)
1608 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1609 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1610 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1611 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1612 strlcat(cachename, modeinfo->name, sizeof(cachename));
1614 // now add all the permutation pretexts
1615 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1617 if (permutation & (1<<i))
1619 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1620 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1621 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1622 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1623 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1627 // keep line numbers correct
1628 vertstrings_list[vertstrings_count++] = "\n";
1629 geomstrings_list[geomstrings_count++] = "\n";
1630 fragstrings_list[fragstrings_count++] = "\n";
1635 R_CompileShader_AddStaticParms(mode, permutation);
1636 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1637 vertstrings_count += shaderstaticparms_count;
1638 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1639 geomstrings_count += shaderstaticparms_count;
1640 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1641 fragstrings_count += shaderstaticparms_count;
1643 // replace spaces in the cachename with _ characters
1644 for (i = 0;cachename[i];i++)
1645 if (cachename[i] == ' ')
1648 // now append the shader text itself
1649 vertstrings_list[vertstrings_count++] = vertexstring;
1650 geomstrings_list[geomstrings_count++] = geometrystring;
1651 fragstrings_list[fragstrings_count++] = fragmentstring;
1653 // if any sources were NULL, clear the respective list
1655 vertstrings_count = 0;
1656 if (!geometrystring)
1657 geomstrings_count = 0;
1658 if (!fragmentstring)
1659 fragstrings_count = 0;
1661 vertstring_length = 0;
1662 for (i = 0;i < vertstrings_count;i++)
1663 vertstring_length += strlen(vertstrings_list[i]);
1664 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1665 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1666 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1668 geomstring_length = 0;
1669 for (i = 0;i < geomstrings_count;i++)
1670 geomstring_length += strlen(geomstrings_list[i]);
1671 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1672 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1673 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1675 fragstring_length = 0;
1676 for (i = 0;i < fragstrings_count;i++)
1677 fragstring_length += strlen(fragstrings_list[i]);
1678 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1679 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1680 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1682 // try to load the cached shader, or generate one
1683 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1685 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1686 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1688 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1692 Mem_Free(vertstring);
1694 Mem_Free(geomstring);
1696 Mem_Free(fragstring);
1698 Mem_Free(vertexstring);
1700 Mem_Free(geometrystring);
1702 Mem_Free(fragmentstring);
1705 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1706 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1707 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1708 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1709 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1710 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1712 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1713 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1714 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1715 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1716 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1717 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1719 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1721 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1722 if (r_hlsl_permutation != perm)
1724 r_hlsl_permutation = perm;
1725 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1727 if (!r_hlsl_permutation->compiled)
1728 R_HLSL_CompilePermutation(perm, mode, permutation);
1729 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1731 // remove features until we find a valid permutation
1733 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1735 // reduce i more quickly whenever it would not remove any bits
1736 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1737 if (!(permutation & j))
1740 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1741 if (!r_hlsl_permutation->compiled)
1742 R_HLSL_CompilePermutation(perm, mode, permutation);
1743 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1746 if (i >= SHADERPERMUTATION_COUNT)
1748 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1749 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1750 return; // no bit left to clear, entire mode is broken
1754 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1755 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1757 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1758 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1759 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1763 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1765 DPSOFTRAST_SetShader(mode, permutation);
1766 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1767 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1768 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1771 void R_GLSL_Restart_f(void)
1773 unsigned int i, limit;
1774 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1775 Mem_Free(glslshaderstring);
1776 glslshaderstring = NULL;
1777 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1778 Mem_Free(hlslshaderstring);
1779 hlslshaderstring = NULL;
1780 switch(vid.renderpath)
1782 case RENDERPATH_D3D9:
1785 r_hlsl_permutation_t *p;
1786 r_hlsl_permutation = NULL;
1787 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1788 for (i = 0;i < limit;i++)
1790 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1792 if (p->vertexshader)
1793 IDirect3DVertexShader9_Release(p->vertexshader);
1795 IDirect3DPixelShader9_Release(p->pixelshader);
1796 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1799 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1803 case RENDERPATH_D3D10:
1804 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1806 case RENDERPATH_D3D11:
1807 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1809 case RENDERPATH_GL20:
1810 case RENDERPATH_GLES2:
1812 r_glsl_permutation_t *p;
1813 r_glsl_permutation = NULL;
1814 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1815 for (i = 0;i < limit;i++)
1817 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1819 GL_Backend_FreeProgram(p->program);
1820 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1823 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1826 case RENDERPATH_GL13:
1827 case RENDERPATH_GL11:
1829 case RENDERPATH_SOFT:
1834 void R_GLSL_DumpShader_f(void)
1839 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1842 FS_Print(file, "/* The engine may define the following macros:\n");
1843 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1844 for (i = 0;i < SHADERMODE_COUNT;i++)
1845 FS_Print(file, glslshadermodeinfo[i].pretext);
1846 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1847 FS_Print(file, shaderpermutationinfo[i].pretext);
1848 FS_Print(file, "*/\n");
1849 FS_Print(file, builtinshaderstring);
1851 Con_Printf("glsl/default.glsl written\n");
1854 Con_Printf("failed to write to glsl/default.glsl\n");
1856 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1859 FS_Print(file, "/* The engine may define the following macros:\n");
1860 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1861 for (i = 0;i < SHADERMODE_COUNT;i++)
1862 FS_Print(file, hlslshadermodeinfo[i].pretext);
1863 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1864 FS_Print(file, shaderpermutationinfo[i].pretext);
1865 FS_Print(file, "*/\n");
1866 FS_Print(file, builtinhlslshaderstring);
1868 Con_Printf("hlsl/default.hlsl written\n");
1871 Con_Printf("failed to write to hlsl/default.hlsl\n");
1874 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1877 texturemode = GL_MODULATE;
1878 switch (vid.renderpath)
1880 case RENDERPATH_D3D9:
1882 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1883 R_Mesh_TexBind(GL20TU_FIRST , first );
1884 R_Mesh_TexBind(GL20TU_SECOND, second);
1887 case RENDERPATH_D3D10:
1888 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1890 case RENDERPATH_D3D11:
1891 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1893 case RENDERPATH_GL20:
1894 case RENDERPATH_GLES2:
1895 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1896 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1897 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1899 case RENDERPATH_GL13:
1900 R_Mesh_TexBind(0, first );
1901 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1902 R_Mesh_TexBind(1, second);
1904 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1906 case RENDERPATH_GL11:
1907 R_Mesh_TexBind(0, first );
1909 case RENDERPATH_SOFT:
1910 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1911 R_Mesh_TexBind(GL20TU_FIRST , first );
1912 R_Mesh_TexBind(GL20TU_SECOND, second);
1917 void R_SetupShader_DepthOrShadow(void)
1919 switch (vid.renderpath)
1921 case RENDERPATH_D3D9:
1923 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1926 case RENDERPATH_D3D10:
1927 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1929 case RENDERPATH_D3D11:
1930 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1932 case RENDERPATH_GL20:
1933 case RENDERPATH_GLES2:
1934 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1936 case RENDERPATH_GL13:
1937 R_Mesh_TexBind(0, 0);
1938 R_Mesh_TexBind(1, 0);
1940 case RENDERPATH_GL11:
1941 R_Mesh_TexBind(0, 0);
1943 case RENDERPATH_SOFT:
1944 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1949 void R_SetupShader_ShowDepth(void)
1951 switch (vid.renderpath)
1953 case RENDERPATH_D3D9:
1955 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1958 case RENDERPATH_D3D10:
1959 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_D3D11:
1962 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964 case RENDERPATH_GL20:
1965 case RENDERPATH_GLES2:
1966 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1968 case RENDERPATH_GL13:
1970 case RENDERPATH_GL11:
1972 case RENDERPATH_SOFT:
1973 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1978 extern qboolean r_shadow_usingdeferredprepass;
1979 extern cvar_t r_shadow_deferred_8bitrange;
1980 extern rtexture_t *r_shadow_attenuationgradienttexture;
1981 extern rtexture_t *r_shadow_attenuation2dtexture;
1982 extern rtexture_t *r_shadow_attenuation3dtexture;
1983 extern qboolean r_shadow_usingshadowmap2d;
1984 extern qboolean r_shadow_usingshadowmaportho;
1985 extern float r_shadow_shadowmap_texturescale[2];
1986 extern float r_shadow_shadowmap_parameters[4];
1987 extern qboolean r_shadow_shadowmapvsdct;
1988 extern qboolean r_shadow_shadowmapsampler;
1989 extern int r_shadow_shadowmappcf;
1990 extern rtexture_t *r_shadow_shadowmap2dtexture;
1991 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1992 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1993 extern matrix4x4_t r_shadow_shadowmapmatrix;
1994 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1995 extern int r_shadow_prepass_width;
1996 extern int r_shadow_prepass_height;
1997 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1998 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1999 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2000 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2001 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2003 #define BLENDFUNC_ALLOWS_COLORMOD 1
2004 #define BLENDFUNC_ALLOWS_FOG 2
2005 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2006 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2007 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2008 static int R_BlendFuncFlags(int src, int dst)
2012 // a blendfunc allows colormod if:
2013 // a) it can never keep the destination pixel invariant, or
2014 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2015 // this is to prevent unintended side effects from colormod
2017 // a blendfunc allows fog if:
2018 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2019 // this is to prevent unintended side effects from fog
2021 // these checks are the output of fogeval.pl
2023 r |= BLENDFUNC_ALLOWS_COLORMOD;
2024 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2025 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2026 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2028 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2031 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2032 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2033 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2034 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2035 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2036 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2037 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2038 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2039 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2041 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2043 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2044 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2051 // select a permutation of the lighting shader appropriate to this
2052 // combination of texture, entity, light source, and fogging, only use the
2053 // minimum features necessary to avoid wasting rendering time in the
2054 // fragment shader on features that are not being used
2055 unsigned int permutation = 0;
2056 unsigned int mode = 0;
2058 static float dummy_colormod[3] = {1, 1, 1};
2059 float *colormod = rsurface.colormod;
2061 matrix4x4_t tempmatrix;
2062 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2063 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2064 permutation |= SHADERPERMUTATION_ALPHAKILL;
2065 if (rsurfacepass == RSURFPASS_BACKGROUND)
2067 // distorted background
2068 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2070 mode = SHADERMODE_WATER;
2071 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2072 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2073 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2075 // this is the right thing to do for wateralpha
2076 GL_BlendFunc(GL_ONE, GL_ZERO);
2077 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2081 // this is the right thing to do for entity alpha
2082 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2083 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2086 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2088 mode = SHADERMODE_REFRACTION;
2089 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2090 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2094 mode = SHADERMODE_GENERIC;
2095 permutation |= SHADERPERMUTATION_DIFFUSE;
2096 GL_BlendFunc(GL_ONE, GL_ZERO);
2097 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2100 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2102 if (r_glsl_offsetmapping.integer)
2104 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2105 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2106 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2107 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2108 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2110 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2111 if (r_glsl_offsetmapping_reliefmapping.integer)
2112 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2115 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2116 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2117 // normalmap (deferred prepass), may use alpha test on diffuse
2118 mode = SHADERMODE_DEFERREDGEOMETRY;
2119 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2120 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2121 GL_BlendFunc(GL_ONE, GL_ZERO);
2122 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2124 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2126 if (r_glsl_offsetmapping.integer)
2128 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2129 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2130 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2131 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2132 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2134 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2135 if (r_glsl_offsetmapping_reliefmapping.integer)
2136 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2139 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2140 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2142 mode = SHADERMODE_LIGHTSOURCE;
2143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2146 permutation |= SHADERPERMUTATION_CUBEFILTER;
2147 if (diffusescale > 0)
2148 permutation |= SHADERPERMUTATION_DIFFUSE;
2149 if (specularscale > 0)
2150 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2151 if (r_refdef.fogenabled)
2152 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2153 if (rsurface.texture->colormapping)
2154 permutation |= SHADERPERMUTATION_COLORMAPPING;
2155 if (r_shadow_usingshadowmap2d)
2157 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2158 if(r_shadow_shadowmapvsdct)
2159 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2161 if (r_shadow_shadowmapsampler)
2162 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2163 if (r_shadow_shadowmappcf > 1)
2164 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2165 else if (r_shadow_shadowmappcf)
2166 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2168 if (rsurface.texture->reflectmasktexture)
2169 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2170 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2171 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2173 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2175 if (r_glsl_offsetmapping.integer)
2177 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2178 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2179 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2180 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2181 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2183 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2184 if (r_glsl_offsetmapping_reliefmapping.integer)
2185 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2188 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2189 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2190 // unshaded geometry (fullbright or ambient model lighting)
2191 mode = SHADERMODE_FLATCOLOR;
2192 ambientscale = diffusescale = specularscale = 0;
2193 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2194 permutation |= SHADERPERMUTATION_GLOW;
2195 if (r_refdef.fogenabled)
2196 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2197 if (rsurface.texture->colormapping)
2198 permutation |= SHADERPERMUTATION_COLORMAPPING;
2199 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2201 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2202 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2204 if (r_shadow_shadowmapsampler)
2205 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2206 if (r_shadow_shadowmappcf > 1)
2207 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2208 else if (r_shadow_shadowmappcf)
2209 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2212 permutation |= SHADERPERMUTATION_REFLECTION;
2213 if (rsurface.texture->reflectmasktexture)
2214 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2215 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2216 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2218 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2220 if (r_glsl_offsetmapping.integer)
2222 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2223 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2224 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2225 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2226 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2228 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2229 if (r_glsl_offsetmapping_reliefmapping.integer)
2230 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2233 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2234 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2235 // directional model lighting
2236 mode = SHADERMODE_LIGHTDIRECTION;
2237 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2238 permutation |= SHADERPERMUTATION_GLOW;
2239 permutation |= SHADERPERMUTATION_DIFFUSE;
2240 if (specularscale > 0)
2241 permutation |= SHADERPERMUTATION_SPECULAR;
2242 if (r_refdef.fogenabled)
2243 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2244 if (rsurface.texture->colormapping)
2245 permutation |= SHADERPERMUTATION_COLORMAPPING;
2246 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2248 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2249 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2251 if (r_shadow_shadowmapsampler)
2252 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2253 if (r_shadow_shadowmappcf > 1)
2254 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2255 else if (r_shadow_shadowmappcf)
2256 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2258 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2259 permutation |= SHADERPERMUTATION_REFLECTION;
2260 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2261 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2262 if (rsurface.texture->reflectmasktexture)
2263 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2264 if (r_shadow_bouncegridtexture)
2266 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2267 if (r_shadow_bouncegriddirectional)
2268 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2270 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2271 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2273 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2275 if (r_glsl_offsetmapping.integer)
2277 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2278 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2279 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2280 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2281 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2283 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2284 if (r_glsl_offsetmapping_reliefmapping.integer)
2285 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2288 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290 // ambient model lighting
2291 mode = SHADERMODE_LIGHTDIRECTION;
2292 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2293 permutation |= SHADERPERMUTATION_GLOW;
2294 if (r_refdef.fogenabled)
2295 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2296 if (rsurface.texture->colormapping)
2297 permutation |= SHADERPERMUTATION_COLORMAPPING;
2298 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2300 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2301 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2303 if (r_shadow_shadowmapsampler)
2304 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2305 if (r_shadow_shadowmappcf > 1)
2306 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2307 else if (r_shadow_shadowmappcf)
2308 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2310 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2311 permutation |= SHADERPERMUTATION_REFLECTION;
2312 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2313 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2314 if (rsurface.texture->reflectmasktexture)
2315 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2316 if (r_shadow_bouncegridtexture)
2318 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2319 if (r_shadow_bouncegriddirectional)
2320 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2322 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2323 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327 if (r_glsl_offsetmapping.integer)
2329 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2330 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2331 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2332 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2333 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2335 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2336 if (r_glsl_offsetmapping_reliefmapping.integer)
2337 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2341 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2343 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2344 permutation |= SHADERPERMUTATION_GLOW;
2345 if (r_refdef.fogenabled)
2346 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2347 if (rsurface.texture->colormapping)
2348 permutation |= SHADERPERMUTATION_COLORMAPPING;
2349 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2351 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2352 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2354 if (r_shadow_shadowmapsampler)
2355 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2356 if (r_shadow_shadowmappcf > 1)
2357 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2358 else if (r_shadow_shadowmappcf)
2359 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2361 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2362 permutation |= SHADERPERMUTATION_REFLECTION;
2363 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2364 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2365 if (rsurface.texture->reflectmasktexture)
2366 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2367 if (FAKELIGHT_ENABLED)
2369 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2370 mode = SHADERMODE_FAKELIGHT;
2371 permutation |= SHADERPERMUTATION_DIFFUSE;
2372 if (specularscale > 0)
2373 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2375 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2377 // deluxemapping (light direction texture)
2378 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2379 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2381 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2382 permutation |= SHADERPERMUTATION_DIFFUSE;
2383 if (specularscale > 0)
2384 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2386 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2388 // fake deluxemapping (uniform light direction in tangentspace)
2389 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2390 permutation |= SHADERPERMUTATION_DIFFUSE;
2391 if (specularscale > 0)
2392 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394 else if (rsurface.uselightmaptexture)
2396 // ordinary lightmapping (q1bsp, q3bsp)
2397 mode = SHADERMODE_LIGHTMAP;
2401 // ordinary vertex coloring (q3bsp)
2402 mode = SHADERMODE_VERTEXCOLOR;
2404 if (r_shadow_bouncegridtexture)
2406 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2407 if (r_shadow_bouncegriddirectional)
2408 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2410 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2414 colormod = dummy_colormod;
2415 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2416 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2417 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2418 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2419 switch(vid.renderpath)
2421 case RENDERPATH_D3D9:
2423 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2424 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2425 R_SetupShader_SetPermutationHLSL(mode, permutation);
2426 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2427 if (mode == SHADERMODE_LIGHTSOURCE)
2429 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2430 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2434 if (mode == SHADERMODE_LIGHTDIRECTION)
2436 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2439 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2440 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2441 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2442 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2443 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2445 if (mode == SHADERMODE_LIGHTSOURCE)
2447 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2448 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2449 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2450 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2451 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2453 // additive passes are only darkened by fog, not tinted
2454 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2455 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2459 if (mode == SHADERMODE_FLATCOLOR)
2461 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2463 else if (mode == SHADERMODE_LIGHTDIRECTION)
2465 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2466 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2467 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2468 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2469 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2470 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2471 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2478 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2479 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2481 // additive passes are only darkened by fog, not tinted
2482 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2483 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2485 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2486 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2487 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2488 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2489 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2490 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2491 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2492 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2493 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2494 if (mode == SHADERMODE_WATER)
2495 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2497 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2499 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2500 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2501 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2502 if (rsurface.texture->pantstexture)
2503 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2505 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2506 if (rsurface.texture->shirttexture)
2507 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2510 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2511 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2512 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2513 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2514 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2515 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2516 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2518 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2519 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2520 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2521 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2522 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2523 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2524 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2525 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2526 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2527 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2528 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2529 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2530 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2531 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2532 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2533 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2534 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2535 if (rsurfacepass == RSURFPASS_BACKGROUND)
2537 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2538 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2539 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2543 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2545 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2546 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2547 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2548 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2549 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2551 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2552 if (rsurface.rtlight)
2554 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2555 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2560 case RENDERPATH_D3D10:
2561 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2563 case RENDERPATH_D3D11:
2564 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2566 case RENDERPATH_GL20:
2567 case RENDERPATH_GLES2:
2568 if (!vid.useinterleavedarrays)
2570 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2571 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2572 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2573 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2574 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2575 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2576 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2577 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2581 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2582 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2584 R_SetupShader_SetPermutationGLSL(mode, permutation);
2585 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2586 if (mode == SHADERMODE_LIGHTSOURCE)
2588 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2589 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2590 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2591 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2592 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2593 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2595 // additive passes are only darkened by fog, not tinted
2596 if (r_glsl_permutation->loc_FogColor >= 0)
2597 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2598 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2602 if (mode == SHADERMODE_FLATCOLOR)
2604 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2606 else if (mode == SHADERMODE_LIGHTDIRECTION)
2608 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2609 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2610 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2611 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2612 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2613 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2614 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2618 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2619 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2620 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2621 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2622 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2624 // additive passes are only darkened by fog, not tinted
2625 if (r_glsl_permutation->loc_FogColor >= 0)
2627 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2628 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2630 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2632 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2633 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2634 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2635 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2636 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2637 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2638 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2639 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2640 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2642 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2643 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2644 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2645 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2646 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2648 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2649 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2650 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2651 if (r_glsl_permutation->loc_Color_Pants >= 0)
2653 if (rsurface.texture->pantstexture)
2654 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2656 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2658 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2660 if (rsurface.texture->shirttexture)
2661 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2663 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2665 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2666 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2667 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2668 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2669 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2670 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2671 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2672 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2673 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2675 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2676 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2677 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2678 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2679 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2680 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2681 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2682 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2683 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2684 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2685 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2686 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2687 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2688 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2689 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2690 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2691 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2692 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2693 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2694 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2695 if (rsurfacepass == RSURFPASS_BACKGROUND)
2697 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2698 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2699 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2703 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2705 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2706 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2707 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2708 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2709 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2711 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2712 if (rsurface.rtlight)
2714 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2715 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2718 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2721 case RENDERPATH_GL13:
2722 case RENDERPATH_GL11:
2724 case RENDERPATH_SOFT:
2725 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2726 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2727 R_SetupShader_SetPermutationSoft(mode, permutation);
2728 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2729 if (mode == SHADERMODE_LIGHTSOURCE)
2731 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2732 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2733 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2734 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2735 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2736 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2738 // additive passes are only darkened by fog, not tinted
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2740 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2744 if (mode == SHADERMODE_FLATCOLOR)
2746 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2748 else if (mode == SHADERMODE_LIGHTDIRECTION)
2750 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2751 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2762 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2763 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2766 // additive passes are only darkened by fog, not tinted
2767 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2768 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2771 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2772 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2773 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2774 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2775 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2776 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2777 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2778 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2779 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2781 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2782 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2783 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2784 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2785 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2788 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2790 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2792 if (rsurface.texture->pantstexture)
2793 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2795 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2797 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2799 if (rsurface.texture->shirttexture)
2800 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2802 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2804 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2805 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2806 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2807 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2808 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2809 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2810 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2812 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2813 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2814 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2815 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2816 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2817 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2818 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2819 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2820 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2821 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2822 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2823 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2824 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2825 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2826 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2827 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2828 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2829 if (rsurfacepass == RSURFPASS_BACKGROUND)
2831 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2832 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2833 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2837 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2839 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2840 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2841 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2842 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2843 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2845 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2846 if (rsurface.rtlight)
2848 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2849 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2856 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2858 // select a permutation of the lighting shader appropriate to this
2859 // combination of texture, entity, light source, and fogging, only use the
2860 // minimum features necessary to avoid wasting rendering time in the
2861 // fragment shader on features that are not being used
2862 unsigned int permutation = 0;
2863 unsigned int mode = 0;
2864 const float *lightcolorbase = rtlight->currentcolor;
2865 float ambientscale = rtlight->ambientscale;
2866 float diffusescale = rtlight->diffusescale;
2867 float specularscale = rtlight->specularscale;
2868 // this is the location of the light in view space
2869 vec3_t viewlightorigin;
2870 // this transforms from view space (camera) to light space (cubemap)
2871 matrix4x4_t viewtolight;
2872 matrix4x4_t lighttoview;
2873 float viewtolight16f[16];
2874 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2876 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2877 if (rtlight->currentcubemap != r_texture_whitecube)
2878 permutation |= SHADERPERMUTATION_CUBEFILTER;
2879 if (diffusescale > 0)
2880 permutation |= SHADERPERMUTATION_DIFFUSE;
2881 if (specularscale > 0)
2882 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2883 if (r_shadow_usingshadowmap2d)
2885 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2886 if (r_shadow_shadowmapvsdct)
2887 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2889 if (r_shadow_shadowmapsampler)
2890 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2891 if (r_shadow_shadowmappcf > 1)
2892 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2893 else if (r_shadow_shadowmappcf)
2894 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2896 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2897 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2898 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2899 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2900 switch(vid.renderpath)
2902 case RENDERPATH_D3D9:
2904 R_SetupShader_SetPermutationHLSL(mode, permutation);
2905 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2906 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2907 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2908 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2909 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2910 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2911 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2912 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2913 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2914 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2916 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2917 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2918 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2919 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2920 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2921 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2924 case RENDERPATH_D3D10:
2925 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2927 case RENDERPATH_D3D11:
2928 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2930 case RENDERPATH_GL20:
2931 case RENDERPATH_GLES2:
2932 R_SetupShader_SetPermutationGLSL(mode, permutation);
2933 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2934 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2935 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2936 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2937 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2938 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2939 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2940 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2941 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2944 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2945 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2946 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2947 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2948 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2949 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2951 case RENDERPATH_GL13:
2952 case RENDERPATH_GL11:
2954 case RENDERPATH_SOFT:
2955 R_SetupShader_SetPermutationGLSL(mode, permutation);
2956 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2957 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2958 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2959 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2960 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2961 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2962 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2963 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2964 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2965 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2967 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2968 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2969 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2970 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2971 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2972 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2977 #define SKINFRAME_HASH 1024
2981 int loadsequence; // incremented each level change
2982 memexpandablearray_t array;
2983 skinframe_t *hash[SKINFRAME_HASH];
2986 r_skinframe_t r_skinframe;
2988 void R_SkinFrame_PrepareForPurge(void)
2990 r_skinframe.loadsequence++;
2991 // wrap it without hitting zero
2992 if (r_skinframe.loadsequence >= 200)
2993 r_skinframe.loadsequence = 1;
2996 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3000 // mark the skinframe as used for the purging code
3001 skinframe->loadsequence = r_skinframe.loadsequence;
3004 void R_SkinFrame_Purge(void)
3008 for (i = 0;i < SKINFRAME_HASH;i++)
3010 for (s = r_skinframe.hash[i];s;s = s->next)
3012 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3014 if (s->merged == s->base)
3016 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3017 R_PurgeTexture(s->stain );s->stain = NULL;
3018 R_PurgeTexture(s->merged);s->merged = NULL;
3019 R_PurgeTexture(s->base );s->base = NULL;
3020 R_PurgeTexture(s->pants );s->pants = NULL;
3021 R_PurgeTexture(s->shirt );s->shirt = NULL;
3022 R_PurgeTexture(s->nmap );s->nmap = NULL;
3023 R_PurgeTexture(s->gloss );s->gloss = NULL;
3024 R_PurgeTexture(s->glow );s->glow = NULL;
3025 R_PurgeTexture(s->fog );s->fog = NULL;
3026 R_PurgeTexture(s->reflect);s->reflect = NULL;
3027 s->loadsequence = 0;
3033 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3035 char basename[MAX_QPATH];
3037 Image_StripImageExtension(name, basename, sizeof(basename));
3039 if( last == NULL ) {
3041 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3042 item = r_skinframe.hash[hashindex];
3047 // linearly search through the hash bucket
3048 for( ; item ; item = item->next ) {
3049 if( !strcmp( item->basename, basename ) ) {
3056 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3060 char basename[MAX_QPATH];
3062 Image_StripImageExtension(name, basename, sizeof(basename));
3064 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3065 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3066 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3070 rtexture_t *dyntexture;
3071 // check whether its a dynamic texture
3072 dyntexture = CL_GetDynTexture( basename );
3073 if (!add && !dyntexture)
3075 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3076 memset(item, 0, sizeof(*item));
3077 strlcpy(item->basename, basename, sizeof(item->basename));
3078 item->base = dyntexture; // either NULL or dyntexture handle
3079 item->textureflags = textureflags;
3080 item->comparewidth = comparewidth;
3081 item->compareheight = compareheight;
3082 item->comparecrc = comparecrc;
3083 item->next = r_skinframe.hash[hashindex];
3084 r_skinframe.hash[hashindex] = item;
3086 else if( item->base == NULL )
3088 rtexture_t *dyntexture;
3089 // check whether its a dynamic texture
3090 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3091 dyntexture = CL_GetDynTexture( basename );
3092 item->base = dyntexture; // either NULL or dyntexture handle
3095 R_SkinFrame_MarkUsed(item);
3099 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3101 unsigned long long avgcolor[5], wsum; \
3109 for(pix = 0; pix < cnt; ++pix) \
3112 for(comp = 0; comp < 3; ++comp) \
3114 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3117 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3119 for(comp = 0; comp < 3; ++comp) \
3120 avgcolor[comp] += getpixel * w; \
3123 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3124 avgcolor[4] += getpixel; \
3126 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3128 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3129 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3130 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3131 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3134 extern cvar_t gl_picmip;
3135 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3138 unsigned char *pixels;
3139 unsigned char *bumppixels;
3140 unsigned char *basepixels = NULL;
3141 int basepixels_width = 0;
3142 int basepixels_height = 0;
3143 skinframe_t *skinframe;
3144 rtexture_t *ddsbase = NULL;
3145 qboolean ddshasalpha = false;
3146 float ddsavgcolor[4];
3147 char basename[MAX_QPATH];
3148 int miplevel = R_PicmipForFlags(textureflags);
3149 int savemiplevel = miplevel;
3152 if (cls.state == ca_dedicated)
3155 // return an existing skinframe if already loaded
3156 // if loading of the first image fails, don't make a new skinframe as it
3157 // would cause all future lookups of this to be missing
3158 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3159 if (skinframe && skinframe->base)
3162 Image_StripImageExtension(name, basename, sizeof(basename));
3164 // check for DDS texture file first
3165 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3167 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3168 if (basepixels == NULL)
3172 // FIXME handle miplevel
3174 if (developer_loading.integer)
3175 Con_Printf("loading skin \"%s\"\n", name);
3177 // we've got some pixels to store, so really allocate this new texture now
3179 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3180 skinframe->stain = NULL;
3181 skinframe->merged = NULL;
3182 skinframe->base = NULL;
3183 skinframe->pants = NULL;
3184 skinframe->shirt = NULL;
3185 skinframe->nmap = NULL;
3186 skinframe->gloss = NULL;
3187 skinframe->glow = NULL;
3188 skinframe->fog = NULL;
3189 skinframe->reflect = NULL;
3190 skinframe->hasalpha = false;
3194 skinframe->base = ddsbase;
3195 skinframe->hasalpha = ddshasalpha;
3196 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3197 if (r_loadfog && skinframe->hasalpha)
3198 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3199 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3203 basepixels_width = image_width;
3204 basepixels_height = image_height;
3205 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3206 if (textureflags & TEXF_ALPHA)
3208 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3210 if (basepixels[j] < 255)
3212 skinframe->hasalpha = true;
3216 if (r_loadfog && skinframe->hasalpha)
3218 // has transparent pixels
3219 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3220 for (j = 0;j < image_width * image_height * 4;j += 4)
3225 pixels[j+3] = basepixels[j+3];
3227 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3231 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3232 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3233 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3234 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3235 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3236 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3241 mymiplevel = savemiplevel;
3242 if (r_loadnormalmap)
3243 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3244 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3246 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3247 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3248 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3249 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3252 // _norm is the name used by tenebrae and has been adopted as standard
3253 if (r_loadnormalmap && skinframe->nmap == NULL)
3255 mymiplevel = savemiplevel;
3256 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3258 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3262 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3264 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3265 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3266 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3268 Mem_Free(bumppixels);
3270 else if (r_shadow_bumpscale_basetexture.value > 0)
3272 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3273 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3274 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3277 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3278 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3281 // _luma is supported only for tenebrae compatibility
3282 // _glow is the preferred name
3283 mymiplevel = savemiplevel;
3284 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3286 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3287 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3288 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3289 Mem_Free(pixels);pixels = NULL;
3292 mymiplevel = savemiplevel;
3293 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3295 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3296 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3297 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3302 mymiplevel = savemiplevel;
3303 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3305 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3306 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3307 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3312 mymiplevel = savemiplevel;
3313 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3315 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3316 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3317 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3322 mymiplevel = savemiplevel;
3323 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3325 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3326 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3327 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3333 Mem_Free(basepixels);
3338 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3339 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3342 unsigned char *temp1, *temp2;
3343 skinframe_t *skinframe;
3345 if (cls.state == ca_dedicated)
3348 // if already loaded just return it, otherwise make a new skinframe
3349 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3350 if (skinframe && skinframe->base)
3353 skinframe->stain = NULL;
3354 skinframe->merged = NULL;
3355 skinframe->base = NULL;
3356 skinframe->pants = NULL;
3357 skinframe->shirt = NULL;
3358 skinframe->nmap = NULL;
3359 skinframe->gloss = NULL;
3360 skinframe->glow = NULL;
3361 skinframe->fog = NULL;
3362 skinframe->reflect = NULL;
3363 skinframe->hasalpha = false;
3365 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3369 if (developer_loading.integer)
3370 Con_Printf("loading 32bit skin \"%s\"\n", name);
3372 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3374 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3375 temp2 = temp1 + width * height * 4;
3376 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3377 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3380 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3381 if (textureflags & TEXF_ALPHA)
3383 for (i = 3;i < width * height * 4;i += 4)
3385 if (skindata[i] < 255)
3387 skinframe->hasalpha = true;
3391 if (r_loadfog && skinframe->hasalpha)
3393 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3394 memcpy(fogpixels, skindata, width * height * 4);
3395 for (i = 0;i < width * height * 4;i += 4)
3396 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3397 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3398 Mem_Free(fogpixels);
3402 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3403 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3408 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3412 skinframe_t *skinframe;
3414 if (cls.state == ca_dedicated)
3417 // if already loaded just return it, otherwise make a new skinframe
3418 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3419 if (skinframe && skinframe->base)
3422 skinframe->stain = NULL;
3423 skinframe->merged = NULL;
3424 skinframe->base = NULL;
3425 skinframe->pants = NULL;
3426 skinframe->shirt = NULL;
3427 skinframe->nmap = NULL;
3428 skinframe->gloss = NULL;
3429 skinframe->glow = NULL;
3430 skinframe->fog = NULL;
3431 skinframe->reflect = NULL;
3432 skinframe->hasalpha = false;
3434 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3438 if (developer_loading.integer)
3439 Con_Printf("loading quake skin \"%s\"\n", name);
3441 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3442 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3443 memcpy(skinframe->qpixels, skindata, width*height);
3444 skinframe->qwidth = width;
3445 skinframe->qheight = height;
3448 for (i = 0;i < width * height;i++)
3449 featuresmask |= palette_featureflags[skindata[i]];
3451 skinframe->hasalpha = false;
3452 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3453 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3454 skinframe->qgeneratemerged = true;
3455 skinframe->qgeneratebase = skinframe->qhascolormapping;
3456 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3458 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3459 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3464 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3468 unsigned char *skindata;
3470 if (!skinframe->qpixels)
3473 if (!skinframe->qhascolormapping)
3474 colormapped = false;
3478 if (!skinframe->qgeneratebase)
3483 if (!skinframe->qgeneratemerged)
3487 width = skinframe->qwidth;
3488 height = skinframe->qheight;
3489 skindata = skinframe->qpixels;
3491 if (skinframe->qgeneratenmap)
3493 unsigned char *temp1, *temp2;
3494 skinframe->qgeneratenmap = false;
3495 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3496 temp2 = temp1 + width * height * 4;
3497 // use either a custom palette or the quake palette
3498 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3499 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3500 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3504 if (skinframe->qgenerateglow)
3506 skinframe->qgenerateglow = false;
3507 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3512 skinframe->qgeneratebase = false;
3513 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3514 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3515 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3519 skinframe->qgeneratemerged = false;
3520 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3523 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3525 Mem_Free(skinframe->qpixels);
3526 skinframe->qpixels = NULL;
3530 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3533 skinframe_t *skinframe;
3535 if (cls.state == ca_dedicated)
3538 // if already loaded just return it, otherwise make a new skinframe
3539 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3540 if (skinframe && skinframe->base)
3543 skinframe->stain = NULL;
3544 skinframe->merged = NULL;
3545 skinframe->base = NULL;
3546 skinframe->pants = NULL;
3547 skinframe->shirt = NULL;
3548 skinframe->nmap = NULL;
3549 skinframe->gloss = NULL;
3550 skinframe->glow = NULL;
3551 skinframe->fog = NULL;
3552 skinframe->reflect = NULL;
3553 skinframe->hasalpha = false;
3555 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3559 if (developer_loading.integer)
3560 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3562 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3563 if (textureflags & TEXF_ALPHA)
3565 for (i = 0;i < width * height;i++)
3567 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3569 skinframe->hasalpha = true;
3573 if (r_loadfog && skinframe->hasalpha)
3574 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3577 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3578 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3583 skinframe_t *R_SkinFrame_LoadMissing(void)
3585 skinframe_t *skinframe;
3587 if (cls.state == ca_dedicated)
3590 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3591 skinframe->stain = NULL;
3592 skinframe->merged = NULL;
3593 skinframe->base = NULL;
3594 skinframe->pants = NULL;
3595 skinframe->shirt = NULL;
3596 skinframe->nmap = NULL;
3597 skinframe->gloss = NULL;
3598 skinframe->glow = NULL;
3599 skinframe->fog = NULL;
3600 skinframe->reflect = NULL;
3601 skinframe->hasalpha = false;
3603 skinframe->avgcolor[0] = rand() / RAND_MAX;
3604 skinframe->avgcolor[1] = rand() / RAND_MAX;
3605 skinframe->avgcolor[2] = rand() / RAND_MAX;
3606 skinframe->avgcolor[3] = 1;
3611 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3612 typedef struct suffixinfo_s
3615 qboolean flipx, flipy, flipdiagonal;
3618 static suffixinfo_t suffix[3][6] =
3621 {"px", false, false, false},
3622 {"nx", false, false, false},
3623 {"py", false, false, false},
3624 {"ny", false, false, false},
3625 {"pz", false, false, false},
3626 {"nz", false, false, false}
3629 {"posx", false, false, false},
3630 {"negx", false, false, false},
3631 {"posy", false, false, false},
3632 {"negy", false, false, false},
3633 {"posz", false, false, false},
3634 {"negz", false, false, false}
3637 {"rt", true, false, true},
3638 {"lf", false, true, true},
3639 {"ft", true, true, false},
3640 {"bk", false, false, false},
3641 {"up", true, false, true},
3642 {"dn", true, false, true}
3646 static int componentorder[4] = {0, 1, 2, 3};
3648 rtexture_t *R_LoadCubemap(const char *basename)
3650 int i, j, cubemapsize;
3651 unsigned char *cubemappixels, *image_buffer;
3652 rtexture_t *cubemaptexture;
3654 // must start 0 so the first loadimagepixels has no requested width/height
3656 cubemappixels = NULL;
3657 cubemaptexture = NULL;
3658 // keep trying different suffix groups (posx, px, rt) until one loads
3659 for (j = 0;j < 3 && !cubemappixels;j++)
3661 // load the 6 images in the suffix group
3662 for (i = 0;i < 6;i++)
3664 // generate an image name based on the base and and suffix
3665 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3667 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3669 // an image loaded, make sure width and height are equal
3670 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3672 // if this is the first image to load successfully, allocate the cubemap memory
3673 if (!cubemappixels && image_width >= 1)
3675 cubemapsize = image_width;
3676 // note this clears to black, so unavailable sides are black
3677 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3679 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3681 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3684 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3686 Mem_Free(image_buffer);
3690 // if a cubemap loaded, upload it
3693 if (developer_loading.integer)
3694 Con_Printf("loading cubemap \"%s\"\n", basename);
3696 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3697 Mem_Free(cubemappixels);
3701 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3702 if (developer_loading.integer)
3704 Con_Printf("(tried tried images ");
3705 for (j = 0;j < 3;j++)
3706 for (i = 0;i < 6;i++)
3707 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3708 Con_Print(" and was unable to find any of them).\n");
3711 return cubemaptexture;
3714 rtexture_t *R_GetCubemap(const char *basename)
3717 for (i = 0;i < r_texture_numcubemaps;i++)
3718 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3719 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3720 if (i >= MAX_CUBEMAPS)
3721 return r_texture_whitecube;
3722 r_texture_numcubemaps++;
3723 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3724 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3725 return r_texture_cubemaps[i].texture;
3728 void R_FreeCubemaps(void)
3731 for (i = 0;i < r_texture_numcubemaps;i++)
3733 if (developer_loading.integer)
3734 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3735 if (r_texture_cubemaps[i].texture)
3736 R_FreeTexture(r_texture_cubemaps[i].texture);
3738 r_texture_numcubemaps = 0;
3741 void R_Main_FreeViewCache(void)
3743 if (r_refdef.viewcache.entityvisible)
3744 Mem_Free(r_refdef.viewcache.entityvisible);
3745 if (r_refdef.viewcache.world_pvsbits)
3746 Mem_Free(r_refdef.viewcache.world_pvsbits);
3747 if (r_refdef.viewcache.world_leafvisible)
3748 Mem_Free(r_refdef.viewcache.world_leafvisible);
3749 if (r_refdef.viewcache.world_surfacevisible)
3750 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3751 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3754 void R_Main_ResizeViewCache(void)
3756 int numentities = r_refdef.scene.numentities;
3757 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3758 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3759 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3760 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3761 if (r_refdef.viewcache.maxentities < numentities)
3763 r_refdef.viewcache.maxentities = numentities;
3764 if (r_refdef.viewcache.entityvisible)
3765 Mem_Free(r_refdef.viewcache.entityvisible);
3766 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3768 if (r_refdef.viewcache.world_numclusters != numclusters)
3770 r_refdef.viewcache.world_numclusters = numclusters;
3771 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3772 if (r_refdef.viewcache.world_pvsbits)
3773 Mem_Free(r_refdef.viewcache.world_pvsbits);
3774 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3776 if (r_refdef.viewcache.world_numleafs != numleafs)
3778 r_refdef.viewcache.world_numleafs = numleafs;
3779 if (r_refdef.viewcache.world_leafvisible)
3780 Mem_Free(r_refdef.viewcache.world_leafvisible);
3781 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3783 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3785 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3786 if (r_refdef.viewcache.world_surfacevisible)
3787 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3788 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3792 extern rtexture_t *loadingscreentexture;
3793 void gl_main_start(void)
3795 loadingscreentexture = NULL;
3796 r_texture_blanknormalmap = NULL;
3797 r_texture_white = NULL;
3798 r_texture_grey128 = NULL;
3799 r_texture_black = NULL;
3800 r_texture_whitecube = NULL;
3801 r_texture_normalizationcube = NULL;
3802 r_texture_fogattenuation = NULL;
3803 r_texture_fogheighttexture = NULL;
3804 r_texture_gammaramps = NULL;
3805 r_texture_numcubemaps = 0;
3807 r_loaddds = r_texture_dds_load.integer != 0;
3808 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3810 switch(vid.renderpath)
3812 case RENDERPATH_GL20:
3813 case RENDERPATH_D3D9:
3814 case RENDERPATH_D3D10:
3815 case RENDERPATH_D3D11:
3816 case RENDERPATH_SOFT:
3817 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3818 Cvar_SetValueQuick(&gl_combine, 1);
3819 Cvar_SetValueQuick(&r_glsl, 1);
3820 r_loadnormalmap = true;
3824 case RENDERPATH_GL13:
3825 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3826 Cvar_SetValueQuick(&gl_combine, 1);
3827 Cvar_SetValueQuick(&r_glsl, 0);
3828 r_loadnormalmap = false;
3829 r_loadgloss = false;
3832 case RENDERPATH_GL11:
3833 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3834 Cvar_SetValueQuick(&gl_combine, 0);
3835 Cvar_SetValueQuick(&r_glsl, 0);
3836 r_loadnormalmap = false;
3837 r_loadgloss = false;
3840 case RENDERPATH_GLES2:
3841 Cvar_SetValueQuick(&r_textureunits, 1);
3842 Cvar_SetValueQuick(&gl_combine, 1);
3843 Cvar_SetValueQuick(&r_glsl, 1);
3844 r_loadnormalmap = true;
3845 r_loadgloss = false;
3851 R_FrameData_Reset();
3855 memset(r_queries, 0, sizeof(r_queries));
3857 r_qwskincache = NULL;
3858 r_qwskincache_size = 0;
3860 // set up r_skinframe loading system for textures
3861 memset(&r_skinframe, 0, sizeof(r_skinframe));
3862 r_skinframe.loadsequence = 1;
3863 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3865 r_main_texturepool = R_AllocTexturePool();
3866 R_BuildBlankTextures();
3868 if (vid.support.arb_texture_cube_map)
3871 R_BuildNormalizationCube();
3873 r_texture_fogattenuation = NULL;
3874 r_texture_fogheighttexture = NULL;
3875 r_texture_gammaramps = NULL;
3876 //r_texture_fogintensity = NULL;
3877 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3878 memset(&r_waterstate, 0, sizeof(r_waterstate));
3879 r_glsl_permutation = NULL;
3880 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3881 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3882 glslshaderstring = NULL;
3884 r_hlsl_permutation = NULL;
3885 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3886 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3888 hlslshaderstring = NULL;
3889 memset(&r_svbsp, 0, sizeof (r_svbsp));
3891 r_refdef.fogmasktable_density = 0;
3894 void gl_main_shutdown(void)
3897 R_FrameData_Reset();
3899 R_Main_FreeViewCache();
3901 switch(vid.renderpath)
3903 case RENDERPATH_GL11:
3904 case RENDERPATH_GL13:
3905 case RENDERPATH_GL20:
3906 case RENDERPATH_GLES2:
3908 qglDeleteQueriesARB(r_maxqueries, r_queries);
3910 case RENDERPATH_D3D9:
3911 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3913 case RENDERPATH_D3D10:
3914 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3916 case RENDERPATH_D3D11:
3917 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3919 case RENDERPATH_SOFT:
3925 memset(r_queries, 0, sizeof(r_queries));
3927 r_qwskincache = NULL;
3928 r_qwskincache_size = 0;
3930 // clear out the r_skinframe state
3931 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3932 memset(&r_skinframe, 0, sizeof(r_skinframe));
3935 Mem_Free(r_svbsp.nodes);
3936 memset(&r_svbsp, 0, sizeof (r_svbsp));
3937 R_FreeTexturePool(&r_main_texturepool);
3938 loadingscreentexture = NULL;
3939 r_texture_blanknormalmap = NULL;
3940 r_texture_white = NULL;
3941 r_texture_grey128 = NULL;
3942 r_texture_black = NULL;
3943 r_texture_whitecube = NULL;
3944 r_texture_normalizationcube = NULL;
3945 r_texture_fogattenuation = NULL;
3946 r_texture_fogheighttexture = NULL;
3947 r_texture_gammaramps = NULL;
3948 r_texture_numcubemaps = 0;
3949 //r_texture_fogintensity = NULL;
3950 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3951 memset(&r_waterstate, 0, sizeof(r_waterstate));
3954 r_glsl_permutation = NULL;
3955 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3956 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3957 glslshaderstring = NULL;
3959 r_hlsl_permutation = NULL;
3960 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3961 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3963 hlslshaderstring = NULL;
3966 extern void CL_ParseEntityLump(char *entitystring);
3967 void gl_main_newmap(void)
3969 // FIXME: move this code to client
3970 char *entities, entname[MAX_QPATH];
3972 Mem_Free(r_qwskincache);
3973 r_qwskincache = NULL;
3974 r_qwskincache_size = 0;
3977 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3978 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3980 CL_ParseEntityLump(entities);
3984 if (cl.worldmodel->brush.entities)
3985 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3987 R_Main_FreeViewCache();
3989 R_FrameData_Reset();
3992 void GL_Main_Init(void)
3994 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3996 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3997 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3998 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3999 if (gamemode == GAME_NEHAHRA)
4001 Cvar_RegisterVariable (&gl_fogenable);
4002 Cvar_RegisterVariable (&gl_fogdensity);
4003 Cvar_RegisterVariable (&gl_fogred);
4004 Cvar_RegisterVariable (&gl_foggreen);
4005 Cvar_RegisterVariable (&gl_fogblue);
4006 Cvar_RegisterVariable (&gl_fogstart);
4007 Cvar_RegisterVariable (&gl_fogend);
4008 Cvar_RegisterVariable (&gl_skyclip);
4010 Cvar_RegisterVariable(&r_motionblur);
4011 Cvar_RegisterVariable(&r_motionblur_maxblur);
4012 Cvar_RegisterVariable(&r_motionblur_bmin);
4013 Cvar_RegisterVariable(&r_motionblur_vmin);
4014 Cvar_RegisterVariable(&r_motionblur_vmax);
4015 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4016 Cvar_RegisterVariable(&r_motionblur_randomize);
4017 Cvar_RegisterVariable(&r_damageblur);
4018 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4019 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4020 Cvar_RegisterVariable(&r_equalize_entities_by);
4021 Cvar_RegisterVariable(&r_equalize_entities_to);
4022 Cvar_RegisterVariable(&r_depthfirst);
4023 Cvar_RegisterVariable(&r_useinfinitefarclip);
4024 Cvar_RegisterVariable(&r_farclip_base);
4025 Cvar_RegisterVariable(&r_farclip_world);
4026 Cvar_RegisterVariable(&r_nearclip);
4027 Cvar_RegisterVariable(&r_showbboxes);
4028 Cvar_RegisterVariable(&r_showsurfaces);
4029 Cvar_RegisterVariable(&r_showtris);
4030 Cvar_RegisterVariable(&r_shownormals);
4031 Cvar_RegisterVariable(&r_showlighting);
4032 Cvar_RegisterVariable(&r_showshadowvolumes);
4033 Cvar_RegisterVariable(&r_showcollisionbrushes);
4034 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4035 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4036 Cvar_RegisterVariable(&r_showdisabledepthtest);
4037 Cvar_RegisterVariable(&r_drawportals);
4038 Cvar_RegisterVariable(&r_drawentities);
4039 Cvar_RegisterVariable(&r_draw2d);
4040 Cvar_RegisterVariable(&r_drawworld);
4041 Cvar_RegisterVariable(&r_cullentities_trace);
4042 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4043 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4044 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4045 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4046 Cvar_RegisterVariable(&r_drawviewmodel);
4047 Cvar_RegisterVariable(&r_drawexteriormodel);
4048 Cvar_RegisterVariable(&r_speeds);
4049 Cvar_RegisterVariable(&r_fullbrights);
4050 Cvar_RegisterVariable(&r_wateralpha);
4051 Cvar_RegisterVariable(&r_dynamic);
4052 Cvar_RegisterVariable(&r_fakelight);
4053 Cvar_RegisterVariable(&r_fakelight_intensity);
4054 Cvar_RegisterVariable(&r_fullbright);
4055 Cvar_RegisterVariable(&r_shadows);
4056 Cvar_RegisterVariable(&r_shadows_darken);
4057 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4058 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4059 Cvar_RegisterVariable(&r_shadows_throwdistance);
4060 Cvar_RegisterVariable(&r_shadows_throwdirection);
4061 Cvar_RegisterVariable(&r_shadows_focus);
4062 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4063 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4064 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4065 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4066 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4067 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4068 Cvar_RegisterVariable(&r_fog_exp2);
4069 Cvar_RegisterVariable(&r_drawfog);
4070 Cvar_RegisterVariable(&r_transparentdepthmasking);
4071 Cvar_RegisterVariable(&r_texture_dds_load);
4072 Cvar_RegisterVariable(&r_texture_dds_save);
4073 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4074 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4075 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4076 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4077 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4078 Cvar_RegisterVariable(&r_textureunits);
4079 Cvar_RegisterVariable(&gl_combine);
4080 Cvar_RegisterVariable(&r_glsl);
4081 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4082 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4083 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4084 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4085 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4086 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4087 Cvar_RegisterVariable(&r_glsl_postprocess);
4088 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4089 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4090 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4091 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4092 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4093 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4094 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4095 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4097 Cvar_RegisterVariable(&r_water);
4098 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4099 Cvar_RegisterVariable(&r_water_clippingplanebias);
4100 Cvar_RegisterVariable(&r_water_refractdistort);
4101 Cvar_RegisterVariable(&r_water_reflectdistort);
4102 Cvar_RegisterVariable(&r_water_scissormode);
4103 Cvar_RegisterVariable(&r_lerpsprites);
4104 Cvar_RegisterVariable(&r_lerpmodels);
4105 Cvar_RegisterVariable(&r_lerplightstyles);
4106 Cvar_RegisterVariable(&r_waterscroll);
4107 Cvar_RegisterVariable(&r_bloom);
4108 Cvar_RegisterVariable(&r_bloom_colorscale);
4109 Cvar_RegisterVariable(&r_bloom_brighten);
4110 Cvar_RegisterVariable(&r_bloom_blur);
4111 Cvar_RegisterVariable(&r_bloom_resolution);
4112 Cvar_RegisterVariable(&r_bloom_colorexponent);
4113 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4114 Cvar_RegisterVariable(&r_hdr);
4115 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4116 Cvar_RegisterVariable(&r_hdr_glowintensity);
4117 Cvar_RegisterVariable(&r_hdr_range);
4118 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4119 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4120 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4121 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4122 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4123 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4124 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4125 Cvar_RegisterVariable(&developer_texturelogging);
4126 Cvar_RegisterVariable(&gl_lightmaps);
4127 Cvar_RegisterVariable(&r_test);
4128 Cvar_RegisterVariable(&r_glsl_saturation);
4129 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4130 Cvar_RegisterVariable(&r_framedatasize);
4131 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4132 Cvar_SetValue("r_fullbrights", 0);
4133 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4135 Cvar_RegisterVariable(&r_track_sprites);
4136 Cvar_RegisterVariable(&r_track_sprites_flags);
4137 Cvar_RegisterVariable(&r_track_sprites_scalew);
4138 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4139 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4140 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4141 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4142 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4145 extern void R_Textures_Init(void);
4146 extern void GL_Draw_Init(void);
4147 extern void GL_Main_Init(void);
4148 extern void R_Shadow_Init(void);
4149 extern void R_Sky_Init(void);
4150 extern void GL_Surf_Init(void);
4151 extern void R_Particles_Init(void);
4152 extern void R_Explosion_Init(void);
4153 extern void gl_backend_init(void);
4154 extern void Sbar_Init(void);
4155 extern void R_LightningBeams_Init(void);
4156 extern void Mod_RenderInit(void);
4157 extern void Font_Init(void);
4159 void Render_Init(void)
4172 R_LightningBeams_Init();
4181 extern char *ENGINE_EXTENSIONS;
4184 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4185 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4186 gl_version = (const char *)qglGetString(GL_VERSION);
4187 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4191 if (!gl_platformextensions)
4192 gl_platformextensions = "";
4194 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4195 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4196 Con_Printf("GL_VERSION: %s\n", gl_version);
4197 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4198 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4200 VID_CheckExtensions();
4202 // LordHavoc: report supported extensions
4203 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4205 // clear to black (loading plaque will be seen over this)
4206 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4209 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4213 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4215 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4218 p = r_refdef.view.frustum + i;
4223 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4227 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4231 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4235 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4239 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4243 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4247 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4251 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4259 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4263 for (i = 0;i < numplanes;i++)
4270 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4274 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4278 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4282 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4286 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4290 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4294 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4298 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4306 //==================================================================================
4308 // LordHavoc: this stores temporary data used within the same frame
4310 typedef struct r_framedata_mem_s
4312 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4313 size_t size; // how much usable space
4314 size_t current; // how much space in use
4315 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4316 size_t wantedsize; // how much space was allocated
4317 unsigned char *data; // start of real data (16byte aligned)
4321 static r_framedata_mem_t *r_framedata_mem;
4323 void R_FrameData_Reset(void)
4325 while (r_framedata_mem)
4327 r_framedata_mem_t *next = r_framedata_mem->purge;
4328 Mem_Free(r_framedata_mem);
4329 r_framedata_mem = next;
4333 void R_FrameData_Resize(void)
4336 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4337 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4338 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4340 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4341 newmem->wantedsize = wantedsize;
4342 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4343 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4344 newmem->current = 0;
4346 newmem->purge = r_framedata_mem;
4347 r_framedata_mem = newmem;
4351 void R_FrameData_NewFrame(void)
4353 R_FrameData_Resize();
4354 if (!r_framedata_mem)
4356 // if we ran out of space on the last frame, free the old memory now
4357 while (r_framedata_mem->purge)
4359 // repeatedly remove the second item in the list, leaving only head
4360 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4361 Mem_Free(r_framedata_mem->purge);
4362 r_framedata_mem->purge = next;
4364 // reset the current mem pointer
4365 r_framedata_mem->current = 0;
4366 r_framedata_mem->mark = 0;
4369 void *R_FrameData_Alloc(size_t size)
4373 // align to 16 byte boundary - the data pointer is already aligned, so we
4374 // only need to ensure the size of every allocation is also aligned
4375 size = (size + 15) & ~15;
4377 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4379 // emergency - we ran out of space, allocate more memory
4380 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4381 R_FrameData_Resize();
4384 data = r_framedata_mem->data + r_framedata_mem->current;
4385 r_framedata_mem->current += size;
4387 // count the usage for stats
4388 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4389 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4391 return (void *)data;
4394 void *R_FrameData_Store(size_t size, void *data)
4396 void *d = R_FrameData_Alloc(size);
4398 memcpy(d, data, size);
4402 void R_FrameData_SetMark(void)
4404 if (!r_framedata_mem)
4406 r_framedata_mem->mark = r_framedata_mem->current;
4409 void R_FrameData_ReturnToMark(void)
4411 if (!r_framedata_mem)
4413 r_framedata_mem->current = r_framedata_mem->mark;
4416 //==================================================================================
4418 // LordHavoc: animcache originally written by Echon, rewritten since then
4421 * Animation cache prevents re-generating mesh data for an animated model
4422 * multiple times in one frame for lighting, shadowing, reflections, etc.
4425 void R_AnimCache_Free(void)
4429 void R_AnimCache_ClearCache(void)
4432 entity_render_t *ent;
4434 for (i = 0;i < r_refdef.scene.numentities;i++)
4436 ent = r_refdef.scene.entities[i];
4437 ent->animcache_vertex3f = NULL;
4438 ent->animcache_normal3f = NULL;
4439 ent->animcache_svector3f = NULL;
4440 ent->animcache_tvector3f = NULL;
4441 ent->animcache_vertexmesh = NULL;
4442 ent->animcache_vertex3fbuffer = NULL;
4443 ent->animcache_vertexmeshbuffer = NULL;
4447 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4451 // check if we need the meshbuffers
4452 if (!vid.useinterleavedarrays)
4455 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4456 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4457 // TODO: upload vertex3f buffer?
4458 if (ent->animcache_vertexmesh)
4460 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4461 for (i = 0;i < numvertices;i++)
4462 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4463 if (ent->animcache_svector3f)
4464 for (i = 0;i < numvertices;i++)
4465 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4466 if (ent->animcache_tvector3f)
4467 for (i = 0;i < numvertices;i++)
4468 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4469 if (ent->animcache_normal3f)
4470 for (i = 0;i < numvertices;i++)
4471 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4472 // TODO: upload vertexmeshbuffer?
4476 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4478 dp_model_t *model = ent->model;
4480 // see if it's already cached this frame
4481 if (ent->animcache_vertex3f)
4483 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4484 if (wantnormals || wanttangents)
4486 if (ent->animcache_normal3f)
4487 wantnormals = false;
4488 if (ent->animcache_svector3f)
4489 wanttangents = false;
4490 if (wantnormals || wanttangents)
4492 numvertices = model->surfmesh.num_vertices;
4494 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4497 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4498 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4500 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4501 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4507 // see if this ent is worth caching
4508 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4510 // get some memory for this entity and generate mesh data
4511 numvertices = model->surfmesh.num_vertices;
4512 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4514 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4517 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4518 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4520 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4521 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4526 void R_AnimCache_CacheVisibleEntities(void)
4529 qboolean wantnormals = true;
4530 qboolean wanttangents = !r_showsurfaces.integer;
4532 switch(vid.renderpath)
4534 case RENDERPATH_GL20:
4535 case RENDERPATH_D3D9:
4536 case RENDERPATH_D3D10:
4537 case RENDERPATH_D3D11:
4538 case RENDERPATH_GLES2:
4540 case RENDERPATH_GL13:
4541 case RENDERPATH_GL11:
4542 wanttangents = false;
4544 case RENDERPATH_SOFT:
4548 if (r_shownormals.integer)
4549 wanttangents = wantnormals = true;
4551 // TODO: thread this
4552 // NOTE: R_PrepareRTLights() also caches entities
4554 for (i = 0;i < r_refdef.scene.numentities;i++)
4555 if (r_refdef.viewcache.entityvisible[i])
4556 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4559 //==================================================================================
4561 static void R_View_UpdateEntityLighting (void)
4564 entity_render_t *ent;
4565 vec3_t tempdiffusenormal, avg;
4566 vec_t f, fa, fd, fdd;
4567 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4569 for (i = 0;i < r_refdef.scene.numentities;i++)
4571 ent = r_refdef.scene.entities[i];
4573 // skip unseen models
4574 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4578 if (ent->model && ent->model->brush.num_leafs)
4580 // TODO: use modellight for r_ambient settings on world?
4581 VectorSet(ent->modellight_ambient, 0, 0, 0);
4582 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4583 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4587 // fetch the lighting from the worldmodel data
4588 VectorClear(ent->modellight_ambient);
4589 VectorClear(ent->modellight_diffuse);
4590 VectorClear(tempdiffusenormal);
4591 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4594 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4596 // complete lightning for lit sprites
4597 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4598 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4600 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4601 org[2] = org[2] + r_overheadsprites_pushback.value;
4602 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4605 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4607 if(ent->flags & RENDER_EQUALIZE)
4609 // first fix up ambient lighting...
4610 if(r_equalize_entities_minambient.value > 0)
4612 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4615 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4616 if(fa < r_equalize_entities_minambient.value * fd)
4619 // fa'/fd' = minambient
4620 // fa'+0.25*fd' = fa+0.25*fd
4622 // fa' = fd' * minambient
4623 // fd'*(0.25+minambient) = fa+0.25*fd
4625 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4626 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4628 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4629 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
4630 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4631 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4636 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4638 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4639 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4643 // adjust brightness and saturation to target
4644 avg[0] = avg[1] = avg[2] = fa / f;
4645 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4646 avg[0] = avg[1] = avg[2] = fd / f;
4647 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4653 VectorSet(ent->modellight_ambient, 1, 1, 1);
4655 // move the light direction into modelspace coordinates for lighting code
4656 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4657 if(VectorLength2(ent->modellight_lightdir) == 0)
4658 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4659 VectorNormalize(ent->modellight_lightdir);
4663 #define MAX_LINEOFSIGHTTRACES 64
4665 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4668 vec3_t boxmins, boxmaxs;
4671 dp_model_t *model = r_refdef.scene.worldmodel;
4673 if (!model || !model->brush.TraceLineOfSight)
4676 // expand the box a little
4677 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4678 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4679 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4680 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4681 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4682 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4684 // return true if eye is inside enlarged box
4685 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4689 VectorCopy(eye, start);
4690 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4691 if (model->brush.TraceLineOfSight(model, start, end))
4694 // try various random positions
4695 for (i = 0;i < numsamples;i++)
4697 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4698 if (model->brush.TraceLineOfSight(model, start, end))
4706 static void R_View_UpdateEntityVisible (void)
4711 entity_render_t *ent;
4713 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4714 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4715 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4716 : RENDER_EXTERIORMODEL;
4717 if (!r_drawviewmodel.integer)
4718 renderimask |= RENDER_VIEWMODEL;
4719 if (!r_drawexteriormodel.integer)
4720 renderimask |= RENDER_EXTERIORMODEL;
4721 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4723 // worldmodel can check visibility
4724 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4725 for (i = 0;i < r_refdef.scene.numentities;i++)
4727 ent = r_refdef.scene.entities[i];
4728 if (!(ent->flags & renderimask))
4729 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)))
4730 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))
4731 r_refdef.viewcache.entityvisible[i] = true;
4733 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4734 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4736 for (i = 0;i < r_refdef.scene.numentities;i++)
4738 ent = r_refdef.scene.entities[i];
4739 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4741 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4743 continue; // temp entities do pvs only
4744 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4745 ent->last_trace_visibility = realtime;
4746 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4747 r_refdef.viewcache.entityvisible[i] = 0;
4754 // no worldmodel or it can't check visibility
4755 for (i = 0;i < r_refdef.scene.numentities;i++)
4757 ent = r_refdef.scene.entities[i];
4758 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));
4763 /// only used if skyrendermasked, and normally returns false
4764 int R_DrawBrushModelsSky (void)
4767 entity_render_t *ent;
4770 for (i = 0;i < r_refdef.scene.numentities;i++)
4772 if (!r_refdef.viewcache.entityvisible[i])
4774 ent = r_refdef.scene.entities[i];
4775 if (!ent->model || !ent->model->DrawSky)
4777 ent->model->DrawSky(ent);
4783 static void R_DrawNoModel(entity_render_t *ent);
4784 static void R_DrawModels(void)
4787 entity_render_t *ent;
4789 for (i = 0;i < r_refdef.scene.numentities;i++)
4791 if (!r_refdef.viewcache.entityvisible[i])
4793 ent = r_refdef.scene.entities[i];
4794 r_refdef.stats.entities++;
4795 if (ent->model && ent->model->Draw != NULL)
4796 ent->model->Draw(ent);
4802 static void R_DrawModelsDepth(void)
4805 entity_render_t *ent;
4807 for (i = 0;i < r_refdef.scene.numentities;i++)
4809 if (!r_refdef.viewcache.entityvisible[i])
4811 ent = r_refdef.scene.entities[i];
4812 if (ent->model && ent->model->DrawDepth != NULL)
4813 ent->model->DrawDepth(ent);
4817 static void R_DrawModelsDebug(void)
4820 entity_render_t *ent;
4822 for (i = 0;i < r_refdef.scene.numentities;i++)
4824 if (!r_refdef.viewcache.entityvisible[i])
4826 ent = r_refdef.scene.entities[i];
4827 if (ent->model && ent->model->DrawDebug != NULL)
4828 ent->model->DrawDebug(ent);
4832 static void R_DrawModelsAddWaterPlanes(void)
4835 entity_render_t *ent;
4837 for (i = 0;i < r_refdef.scene.numentities;i++)
4839 if (!r_refdef.viewcache.entityvisible[i])
4841 ent = r_refdef.scene.entities[i];
4842 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4843 ent->model->DrawAddWaterPlanes(ent);
4847 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4849 if (r_hdr_irisadaptation.integer)
4853 vec3_t diffusenormal;
4858 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4859 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4860 brightness = max(0.0000001f, brightness);
4861 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4862 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4863 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4864 current = r_hdr_irisadaptation_value.value;
4866 current = min(current + adjust, goal);
4867 else if (current > goal)
4868 current = max(current - adjust, goal);
4869 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4870 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4872 else if (r_hdr_irisadaptation_value.value != 1.0f)
4873 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4876 static void R_View_SetFrustum(const int *scissor)
4879 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4880 vec3_t forward, left, up, origin, v;
4884 // flipped x coordinates (because x points left here)
4885 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4886 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4888 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4889 switch(vid.renderpath)
4891 case RENDERPATH_D3D9:
4892 case RENDERPATH_D3D10:
4893 case RENDERPATH_D3D11:
4894 case RENDERPATH_SOFT:
4895 // non-flipped y coordinates
4896 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4897 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4899 case RENDERPATH_GL11:
4900 case RENDERPATH_GL13:
4901 case RENDERPATH_GL20:
4902 case RENDERPATH_GLES2:
4903 // non-flipped y coordinates
4904 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4905 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4910 // we can't trust r_refdef.view.forward and friends in reflected scenes
4911 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4914 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4915 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4916 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4917 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4918 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4919 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4920 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4921 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4922 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4923 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4924 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4925 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4929 zNear = r_refdef.nearclip;
4930 nudge = 1.0 - 1.0 / (1<<23);
4931 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4932 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4933 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4934 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4935 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4936 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4937 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4938 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4944 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4945 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4946 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4947 r_refdef.view.frustum[0].dist = m[15] - m[12];
4949 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4950 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4951 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4952 r_refdef.view.frustum[1].dist = m[15] + m[12];
4954 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4955 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4956 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4957 r_refdef.view.frustum[2].dist = m[15] - m[13];
4959 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4960 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4961 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4962 r_refdef.view.frustum[3].dist = m[15] + m[13];
4964 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4965 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4966 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4967 r_refdef.view.frustum[4].dist = m[15] - m[14];
4969 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4970 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4971 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4972 r_refdef.view.frustum[5].dist = m[15] + m[14];
4975 if (r_refdef.view.useperspective)
4977 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4978 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]);
4979 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]);
4980 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]);
4981 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]);
4983 // then the normals from the corners relative to origin
4984 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4985 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4986 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4987 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4989 // in a NORMAL view, forward cross left == up
4990 // in a REFLECTED view, forward cross left == down
4991 // so our cross products above need to be adjusted for a left handed coordinate system
4992 CrossProduct(forward, left, v);
4993 if(DotProduct(v, up) < 0)
4995 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4996 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4997 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4998 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5001 // Leaving those out was a mistake, those were in the old code, and they
5002 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5003 // I couldn't reproduce it after adding those normalizations. --blub
5004 VectorNormalize(r_refdef.view.frustum[0].normal);
5005 VectorNormalize(r_refdef.view.frustum[1].normal);
5006 VectorNormalize(r_refdef.view.frustum[2].normal);
5007 VectorNormalize(r_refdef.view.frustum[3].normal);
5009 // make the corners absolute
5010 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5011 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5012 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5013 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5016 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5018 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5019 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5020 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5021 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5022 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5026 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5027 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5028 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5029 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5030 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5031 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5032 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5033 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5034 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5035 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5037 r_refdef.view.numfrustumplanes = 5;
5039 if (r_refdef.view.useclipplane)
5041 r_refdef.view.numfrustumplanes = 6;
5042 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5045 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5046 PlaneClassify(r_refdef.view.frustum + i);
5048 // LordHavoc: note to all quake engine coders, Quake had a special case
5049 // for 90 degrees which assumed a square view (wrong), so I removed it,
5050 // Quake2 has it disabled as well.
5052 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5053 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5054 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5055 //PlaneClassify(&frustum[0]);
5057 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5058 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5059 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5060 //PlaneClassify(&frustum[1]);
5062 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5063 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5064 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5065 //PlaneClassify(&frustum[2]);
5067 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5068 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5069 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5070 //PlaneClassify(&frustum[3]);
5073 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5074 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5075 //PlaneClassify(&frustum[4]);
5078 void R_View_UpdateWithScissor(const int *myscissor)
5080 R_Main_ResizeViewCache();
5081 R_View_SetFrustum(myscissor);
5082 R_View_WorldVisibility(r_refdef.view.useclipplane);
5083 R_View_UpdateEntityVisible();
5084 R_View_UpdateEntityLighting();
5087 void R_View_Update(void)
5089 R_Main_ResizeViewCache();
5090 R_View_SetFrustum(NULL);
5091 R_View_WorldVisibility(r_refdef.view.useclipplane);
5092 R_View_UpdateEntityVisible();
5093 R_View_UpdateEntityLighting();
5096 void R_SetupView(qboolean allowwaterclippingplane)
5098 const float *customclipplane = NULL;
5100 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5102 // LordHavoc: couldn't figure out how to make this approach the
5103 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5104 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5105 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5106 dist = r_refdef.view.clipplane.dist;
5107 plane[0] = r_refdef.view.clipplane.normal[0];
5108 plane[1] = r_refdef.view.clipplane.normal[1];
5109 plane[2] = r_refdef.view.clipplane.normal[2];
5111 customclipplane = plane;
5114 if (!r_refdef.view.useperspective)
5115 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);
5116 else if (vid.stencil && r_useinfinitefarclip.integer)
5117 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);
5119 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);
5120 R_SetViewport(&r_refdef.view.viewport);
5123 void R_EntityMatrix(const matrix4x4_t *matrix)
5125 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5127 gl_modelmatrixchanged = false;
5128 gl_modelmatrix = *matrix;
5129 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5130 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5131 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5132 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5134 switch(vid.renderpath)
5136 case RENDERPATH_D3D9:
5138 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5139 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5142 case RENDERPATH_D3D10:
5143 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5145 case RENDERPATH_D3D11:
5146 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5148 case RENDERPATH_GL13:
5149 case RENDERPATH_GL11:
5150 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5152 case RENDERPATH_SOFT:
5153 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5154 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5156 case RENDERPATH_GL20:
5157 case RENDERPATH_GLES2:
5158 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5159 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5165 void R_ResetViewRendering2D(void)
5167 r_viewport_t viewport;
5170 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5171 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);
5172 R_SetViewport(&viewport);
5173 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5174 GL_Color(1, 1, 1, 1);
5175 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5176 GL_BlendFunc(GL_ONE, GL_ZERO);
5177 GL_ScissorTest(false);
5178 GL_DepthMask(false);
5179 GL_DepthRange(0, 1);
5180 GL_DepthTest(false);
5181 GL_DepthFunc(GL_LEQUAL);
5182 R_EntityMatrix(&identitymatrix);
5183 R_Mesh_ResetTextureState();
5184 GL_PolygonOffset(0, 0);
5185 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5186 switch(vid.renderpath)
5188 case RENDERPATH_GL11:
5189 case RENDERPATH_GL13:
5190 case RENDERPATH_GL20:
5191 case RENDERPATH_GLES2:
5192 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5194 case RENDERPATH_D3D9:
5195 case RENDERPATH_D3D10:
5196 case RENDERPATH_D3D11:
5197 case RENDERPATH_SOFT:
5200 GL_CullFace(GL_NONE);
5203 void R_ResetViewRendering3D(void)
5208 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5209 GL_Color(1, 1, 1, 1);
5210 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5211 GL_BlendFunc(GL_ONE, GL_ZERO);
5212 GL_ScissorTest(true);
5214 GL_DepthRange(0, 1);
5216 GL_DepthFunc(GL_LEQUAL);
5217 R_EntityMatrix(&identitymatrix);
5218 R_Mesh_ResetTextureState();
5219 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5220 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5221 switch(vid.renderpath)
5223 case RENDERPATH_GL11:
5224 case RENDERPATH_GL13:
5225 case RENDERPATH_GL20:
5226 case RENDERPATH_GLES2:
5227 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5229 case RENDERPATH_D3D9:
5230 case RENDERPATH_D3D10:
5231 case RENDERPATH_D3D11:
5232 case RENDERPATH_SOFT:
5235 GL_CullFace(r_refdef.view.cullface_back);
5240 R_RenderView_UpdateViewVectors
5243 static void R_RenderView_UpdateViewVectors(void)
5245 // break apart the view matrix into vectors for various purposes
5246 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5247 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5248 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5249 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5250 // make an inverted copy of the view matrix for tracking sprites
5251 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5254 void R_RenderScene(void);
5255 void R_RenderWaterPlanes(void);
5257 static void R_Water_StartFrame(void)
5260 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5261 r_waterstate_waterplane_t *p;
5263 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5266 switch(vid.renderpath)
5268 case RENDERPATH_GL20:
5269 case RENDERPATH_D3D9:
5270 case RENDERPATH_D3D10:
5271 case RENDERPATH_D3D11:
5272 case RENDERPATH_SOFT:
5273 case RENDERPATH_GLES2:
5275 case RENDERPATH_GL13:
5276 case RENDERPATH_GL11:
5280 // set waterwidth and waterheight to the water resolution that will be
5281 // used (often less than the screen resolution for faster rendering)
5282 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5283 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5285 // calculate desired texture sizes
5286 // can't use water if the card does not support the texture size
5287 if (!r_water.integer || r_showsurfaces.integer)
5288 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5289 else if (vid.support.arb_texture_non_power_of_two)
5291 texturewidth = waterwidth;
5292 textureheight = waterheight;
5293 camerawidth = waterwidth;
5294 cameraheight = waterheight;
5298 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5299 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5300 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5301 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5304 // allocate textures as needed
5305 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5307 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5308 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5310 if (p->texture_refraction)
5311 R_FreeTexture(p->texture_refraction);
5312 p->texture_refraction = NULL;
5313 if (p->texture_reflection)
5314 R_FreeTexture(p->texture_reflection);
5315 p->texture_reflection = NULL;
5316 if (p->texture_camera)
5317 R_FreeTexture(p->texture_camera);
5318 p->texture_camera = NULL;
5320 memset(&r_waterstate, 0, sizeof(r_waterstate));
5321 r_waterstate.texturewidth = texturewidth;
5322 r_waterstate.textureheight = textureheight;
5323 r_waterstate.camerawidth = camerawidth;
5324 r_waterstate.cameraheight = cameraheight;
5327 if (r_waterstate.texturewidth)
5329 r_waterstate.enabled = true;
5331 // when doing a reduced render (HDR) we want to use a smaller area
5332 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5333 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5335 // set up variables that will be used in shader setup
5336 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5337 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5338 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5339 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5342 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5343 r_waterstate.numwaterplanes = 0;
5346 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5348 int triangleindex, planeindex;
5354 r_waterstate_waterplane_t *p;
5355 texture_t *t = R_GetCurrentTexture(surface->texture);
5357 // just use the first triangle with a valid normal for any decisions
5358 VectorClear(normal);
5359 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5361 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5362 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5363 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5364 TriangleNormal(vert[0], vert[1], vert[2], normal);
5365 if (VectorLength2(normal) >= 0.001)
5369 VectorCopy(normal, plane.normal);
5370 VectorNormalize(plane.normal);
5371 plane.dist = DotProduct(vert[0], plane.normal);
5372 PlaneClassify(&plane);
5373 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5375 // skip backfaces (except if nocullface is set)
5376 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5378 VectorNegate(plane.normal, plane.normal);
5380 PlaneClassify(&plane);
5384 // find a matching plane if there is one
5385 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5386 if(p->camera_entity == t->camera_entity)
5387 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5389 if (planeindex >= r_waterstate.maxwaterplanes)
5390 return; // nothing we can do, out of planes
5392 // if this triangle does not fit any known plane rendered this frame, add one
5393 if (planeindex >= r_waterstate.numwaterplanes)
5395 // store the new plane
5396 r_waterstate.numwaterplanes++;
5398 // clear materialflags and pvs
5399 p->materialflags = 0;
5400 p->pvsvalid = false;
5401 p->camera_entity = t->camera_entity;
5402 VectorCopy(surface->mins, p->mins);
5403 VectorCopy(surface->maxs, p->maxs);
5408 p->mins[0] = min(p->mins[0], surface->mins[0]);
5409 p->mins[1] = min(p->mins[1], surface->mins[1]);
5410 p->mins[2] = min(p->mins[2], surface->mins[2]);
5411 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5412 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5413 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5415 // merge this surface's materialflags into the waterplane
5416 p->materialflags |= t->currentmaterialflags;
5417 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5419 // merge this surface's PVS into the waterplane
5420 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5421 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5422 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5424 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5430 static void R_Water_ProcessPlanes(void)
5433 r_refdef_view_t originalview;
5434 r_refdef_view_t myview;
5436 r_waterstate_waterplane_t *p;
5439 originalview = r_refdef.view;
5441 // make sure enough textures are allocated
5442 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5444 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5446 if (!p->texture_refraction)
5447 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);
5448 if (!p->texture_refraction)
5451 else if (p->materialflags & MATERIALFLAG_CAMERA)
5453 if (!p->texture_camera)
5454 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);
5455 if (!p->texture_camera)
5459 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5461 if (!p->texture_reflection)
5462 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);
5463 if (!p->texture_reflection)
5469 r_refdef.view = originalview;
5470 r_refdef.view.showdebug = false;
5471 r_refdef.view.width = r_waterstate.waterwidth;
5472 r_refdef.view.height = r_waterstate.waterheight;
5473 r_refdef.view.useclipplane = true;
5474 myview = r_refdef.view;
5475 r_waterstate.renderingscene = true;
5476 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5478 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5480 r_refdef.view = myview;
5481 if(r_water_scissormode.integer)
5484 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5485 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5488 // render reflected scene and copy into texture
5489 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5490 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5491 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5492 r_refdef.view.clipplane = p->plane;
5494 // reverse the cullface settings for this render
5495 r_refdef.view.cullface_front = GL_FRONT;
5496 r_refdef.view.cullface_back = GL_BACK;
5497 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5499 r_refdef.view.usecustompvs = true;
5501 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5503 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5506 R_ResetViewRendering3D();
5507 R_ClearScreen(r_refdef.fogenabled);
5508 if(r_water_scissormode.integer & 2)
5509 R_View_UpdateWithScissor(myscissor);
5512 if(r_water_scissormode.integer & 1)
5513 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5516 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);
5519 // render the normal view scene and copy into texture
5520 // (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)
5521 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5523 r_refdef.view = myview;
5524 if(r_water_scissormode.integer)
5527 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5528 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5531 r_waterstate.renderingrefraction = true;
5533 r_refdef.view.clipplane = p->plane;
5534 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5535 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5537 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5539 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5540 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5541 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5542 R_RenderView_UpdateViewVectors();
5543 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5545 r_refdef.view.usecustompvs = true;
5546 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);
5550 PlaneClassify(&r_refdef.view.clipplane);
5552 R_ResetViewRendering3D();
5553 R_ClearScreen(r_refdef.fogenabled);
5554 if(r_water_scissormode.integer & 2)
5555 R_View_UpdateWithScissor(myscissor);
5558 if(r_water_scissormode.integer & 1)
5559 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5562 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);
5563 r_waterstate.renderingrefraction = false;
5565 else if (p->materialflags & MATERIALFLAG_CAMERA)
5567 r_refdef.view = myview;
5569 r_refdef.view.clipplane = p->plane;
5570 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5571 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5573 r_refdef.view.width = r_waterstate.camerawidth;
5574 r_refdef.view.height = r_waterstate.cameraheight;
5575 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5576 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5578 if(p->camera_entity)
5580 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5581 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5584 // note: all of the view is used for displaying... so
5585 // there is no use in scissoring
5587 // reverse the cullface settings for this render
5588 r_refdef.view.cullface_front = GL_FRONT;
5589 r_refdef.view.cullface_back = GL_BACK;
5590 // also reverse the view matrix
5591 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
5592 R_RenderView_UpdateViewVectors();
5593 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5595 r_refdef.view.usecustompvs = true;
5596 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);
5599 // camera needs no clipplane
5600 r_refdef.view.useclipplane = false;
5602 PlaneClassify(&r_refdef.view.clipplane);
5604 R_ResetViewRendering3D();
5605 R_ClearScreen(r_refdef.fogenabled);
5609 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);
5610 r_waterstate.renderingrefraction = false;
5614 r_waterstate.renderingscene = false;
5615 r_refdef.view = originalview;
5616 R_ResetViewRendering3D();
5617 R_ClearScreen(r_refdef.fogenabled);
5621 r_refdef.view = originalview;
5622 r_waterstate.renderingscene = false;
5623 Cvar_SetValueQuick(&r_water, 0);
5624 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5628 void R_Bloom_StartFrame(void)
5630 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5632 switch(vid.renderpath)
5634 case RENDERPATH_GL20:
5635 case RENDERPATH_D3D9:
5636 case RENDERPATH_D3D10:
5637 case RENDERPATH_D3D11:
5638 case RENDERPATH_SOFT:
5639 case RENDERPATH_GLES2:
5641 case RENDERPATH_GL13:
5642 case RENDERPATH_GL11:
5646 // set bloomwidth and bloomheight to the bloom resolution that will be
5647 // used (often less than the screen resolution for faster rendering)
5648 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5649 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5650 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5651 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5652 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5654 // calculate desired texture sizes
5655 if (vid.support.arb_texture_non_power_of_two)
5657 screentexturewidth = r_refdef.view.width;
5658 screentextureheight = r_refdef.view.height;
5659 bloomtexturewidth = r_bloomstate.bloomwidth;
5660 bloomtextureheight = r_bloomstate.bloomheight;
5664 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5665 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5666 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5667 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5670 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))
5672 Cvar_SetValueQuick(&r_hdr, 0);
5673 Cvar_SetValueQuick(&r_bloom, 0);
5674 Cvar_SetValueQuick(&r_motionblur, 0);
5675 Cvar_SetValueQuick(&r_damageblur, 0);
5678 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)))
5679 screentexturewidth = screentextureheight = 0;
5680 if (!r_hdr.integer && !r_bloom.integer)
5681 bloomtexturewidth = bloomtextureheight = 0;
5683 // allocate textures as needed
5684 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5686 if (r_bloomstate.texture_screen)
5687 R_FreeTexture(r_bloomstate.texture_screen);
5688 r_bloomstate.texture_screen = NULL;
5689 r_bloomstate.screentexturewidth = screentexturewidth;
5690 r_bloomstate.screentextureheight = screentextureheight;
5691 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5692 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);
5694 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5696 if (r_bloomstate.texture_bloom)
5697 R_FreeTexture(r_bloomstate.texture_bloom);
5698 r_bloomstate.texture_bloom = NULL;
5699 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5700 r_bloomstate.bloomtextureheight = bloomtextureheight;
5701 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5702 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);
5705 // when doing a reduced render (HDR) we want to use a smaller area
5706 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5707 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5708 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5709 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5710 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5712 // set up a texcoord array for the full resolution screen image
5713 // (we have to keep this around to copy back during final render)
5714 r_bloomstate.screentexcoord2f[0] = 0;
5715 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5716 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5717 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5718 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5719 r_bloomstate.screentexcoord2f[5] = 0;
5720 r_bloomstate.screentexcoord2f[6] = 0;
5721 r_bloomstate.screentexcoord2f[7] = 0;
5723 // set up a texcoord array for the reduced resolution bloom image
5724 // (which will be additive blended over the screen image)
5725 r_bloomstate.bloomtexcoord2f[0] = 0;
5726 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5727 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5728 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5729 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5730 r_bloomstate.bloomtexcoord2f[5] = 0;
5731 r_bloomstate.bloomtexcoord2f[6] = 0;
5732 r_bloomstate.bloomtexcoord2f[7] = 0;
5734 switch(vid.renderpath)
5736 case RENDERPATH_GL11:
5737 case RENDERPATH_GL13:
5738 case RENDERPATH_GL20:
5739 case RENDERPATH_SOFT:
5740 case RENDERPATH_GLES2:
5742 case RENDERPATH_D3D9:
5743 case RENDERPATH_D3D10:
5744 case RENDERPATH_D3D11:
5747 for (i = 0;i < 4;i++)
5749 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5750 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5751 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5752 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5758 if (r_hdr.integer || r_bloom.integer)
5760 r_bloomstate.enabled = true;
5761 r_bloomstate.hdr = r_hdr.integer != 0;
5764 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);
5767 void R_Bloom_CopyBloomTexture(float colorscale)
5769 r_refdef.stats.bloom++;
5771 // scale down screen texture to the bloom texture size
5773 R_SetViewport(&r_bloomstate.viewport);
5774 GL_BlendFunc(GL_ONE, GL_ZERO);
5775 GL_Color(colorscale, colorscale, colorscale, 1);
5776 // 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...
5777 switch(vid.renderpath)
5779 case RENDERPATH_GL11:
5780 case RENDERPATH_GL13:
5781 case RENDERPATH_GL20:
5782 case RENDERPATH_SOFT:
5783 case RENDERPATH_GLES2:
5784 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5786 case RENDERPATH_D3D9:
5787 case RENDERPATH_D3D10:
5788 case RENDERPATH_D3D11:
5789 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5792 // TODO: do boxfilter scale-down in shader?
5793 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5794 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5795 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5797 // we now have a bloom image in the framebuffer
5798 // copy it into the bloom image texture for later processing
5799 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);
5800 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5803 void R_Bloom_CopyHDRTexture(void)
5805 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);
5806 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5809 void R_Bloom_MakeTexture(void)
5812 float xoffset, yoffset, r, brighten;
5814 r_refdef.stats.bloom++;
5816 R_ResetViewRendering2D();
5818 // we have a bloom image in the framebuffer
5820 R_SetViewport(&r_bloomstate.viewport);
5822 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5825 r = bound(0, r_bloom_colorexponent.value / x, 1);
5826 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5828 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5829 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5830 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5831 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5833 // copy the vertically blurred bloom view to a texture
5834 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);
5835 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5838 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5839 brighten = r_bloom_brighten.value;
5841 brighten *= r_hdr_range.value;
5842 brighten = sqrt(brighten);
5844 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5845 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5847 for (dir = 0;dir < 2;dir++)
5849 // blend on at multiple vertical offsets to achieve a vertical blur
5850 // TODO: do offset blends using GLSL
5851 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5852 GL_BlendFunc(GL_ONE, GL_ZERO);
5853 for (x = -range;x <= range;x++)
5855 if (!dir){xoffset = 0;yoffset = x;}
5856 else {xoffset = x;yoffset = 0;}
5857 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5858 yoffset /= (float)r_bloomstate.bloomtextureheight;
5859 // compute a texcoord array with the specified x and y offset
5860 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5861 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5862 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5863 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5864 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5865 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5866 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5867 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5868 // this r value looks like a 'dot' particle, fading sharply to
5869 // black at the edges
5870 // (probably not realistic but looks good enough)
5871 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5872 //r = brighten/(range*2+1);
5873 r = brighten / (range * 2 + 1);
5875 r *= (1 - x*x/(float)(range*range));
5876 GL_Color(r, r, r, 1);
5877 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5878 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5879 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5880 GL_BlendFunc(GL_ONE, GL_ONE);
5883 // copy the vertically blurred bloom view to a texture
5884 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);
5885 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5889 void R_HDR_RenderBloomTexture(void)
5891 int oldwidth, oldheight;
5892 float oldcolorscale;
5893 qboolean oldwaterstate;
5895 oldwaterstate = r_waterstate.enabled;
5896 oldcolorscale = r_refdef.view.colorscale;
5897 oldwidth = r_refdef.view.width;
5898 oldheight = r_refdef.view.height;
5899 r_refdef.view.width = r_bloomstate.bloomwidth;
5900 r_refdef.view.height = r_bloomstate.bloomheight;
5902 if(r_hdr.integer < 2)
5903 r_waterstate.enabled = false;
5905 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5906 // TODO: add exposure compensation features
5907 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5909 r_refdef.view.showdebug = false;
5910 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5912 R_ResetViewRendering3D();
5914 R_ClearScreen(r_refdef.fogenabled);
5915 if (r_timereport_active)
5916 R_TimeReport("HDRclear");
5919 if (r_timereport_active)
5920 R_TimeReport("visibility");
5922 // only do secondary renders with HDR if r_hdr is 2 or higher
5923 r_waterstate.numwaterplanes = 0;
5924 if (r_waterstate.enabled)
5925 R_RenderWaterPlanes();
5927 r_refdef.view.showdebug = true;
5929 r_waterstate.numwaterplanes = 0;
5931 R_ResetViewRendering2D();
5933 R_Bloom_CopyHDRTexture();
5934 R_Bloom_MakeTexture();
5936 // restore the view settings
5937 r_waterstate.enabled = oldwaterstate;
5938 r_refdef.view.width = oldwidth;
5939 r_refdef.view.height = oldheight;
5940 r_refdef.view.colorscale = oldcolorscale;
5942 R_ResetViewRendering3D();
5944 R_ClearScreen(r_refdef.fogenabled);
5945 if (r_timereport_active)
5946 R_TimeReport("viewclear");
5949 static void R_BlendView(void)
5951 unsigned int permutation;
5952 float uservecs[4][4];
5954 switch (vid.renderpath)
5956 case RENDERPATH_GL20:
5957 case RENDERPATH_D3D9:
5958 case RENDERPATH_D3D10:
5959 case RENDERPATH_D3D11:
5960 case RENDERPATH_SOFT:
5961 case RENDERPATH_GLES2:
5963 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5964 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5965 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5966 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5967 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5969 if (r_bloomstate.texture_screen)
5971 // make sure the buffer is available
5972 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5974 R_ResetViewRendering2D();
5976 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5978 // declare variables
5980 static float avgspeed;
5982 speed = VectorLength(cl.movement_velocity);
5984 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5985 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5987 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5988 speed = bound(0, speed, 1);
5989 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5991 // calculate values into a standard alpha
5992 cl.motionbluralpha = 1 - exp(-
5994 (r_motionblur.value * speed / 80)
5996 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5999 max(0.0001, cl.time - cl.oldtime) // fps independent
6002 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6003 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6005 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6007 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6008 GL_Color(1, 1, 1, cl.motionbluralpha);
6009 switch(vid.renderpath)
6011 case RENDERPATH_GL11:
6012 case RENDERPATH_GL13:
6013 case RENDERPATH_GL20:
6014 case RENDERPATH_SOFT:
6015 case RENDERPATH_GLES2:
6016 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6018 case RENDERPATH_D3D9:
6019 case RENDERPATH_D3D10:
6020 case RENDERPATH_D3D11:
6021 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6024 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6025 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6026 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6030 // copy view into the screen texture
6031 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);
6032 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6034 else if (!r_bloomstate.texture_bloom)
6036 // we may still have to do view tint...
6037 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6039 // apply a color tint to the whole view
6040 R_ResetViewRendering2D();
6041 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6042 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6043 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6044 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6045 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6047 break; // no screen processing, no bloom, skip it
6050 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6052 // render simple bloom effect
6053 // copy the screen and shrink it and darken it for the bloom process
6054 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6055 // make the bloom texture
6056 R_Bloom_MakeTexture();
6059 #if _MSC_VER >= 1400
6060 #define sscanf sscanf_s
6062 memset(uservecs, 0, sizeof(uservecs));
6063 if (r_glsl_postprocess_uservec1_enable.integer)
6064 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6065 if (r_glsl_postprocess_uservec2_enable.integer)
6066 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6067 if (r_glsl_postprocess_uservec3_enable.integer)
6068 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6069 if (r_glsl_postprocess_uservec4_enable.integer)
6070 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6072 R_ResetViewRendering2D();
6073 GL_Color(1, 1, 1, 1);
6074 GL_BlendFunc(GL_ONE, GL_ZERO);
6076 switch(vid.renderpath)
6078 case RENDERPATH_GL20:
6079 case RENDERPATH_GLES2:
6080 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6081 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6082 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6083 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6084 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6085 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]);
6086 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6087 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]);
6088 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]);
6089 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]);
6090 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]);
6091 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6092 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6093 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);
6095 case RENDERPATH_D3D9:
6097 // 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...
6098 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6099 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6100 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6101 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6102 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6103 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6104 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6105 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6106 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6107 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6108 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6109 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6110 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6111 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6114 case RENDERPATH_D3D10:
6115 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6117 case RENDERPATH_D3D11:
6118 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6120 case RENDERPATH_SOFT:
6121 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6122 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6123 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6124 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6125 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6126 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6127 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6128 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6129 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6130 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6131 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6132 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6133 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6134 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6139 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6140 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6142 case RENDERPATH_GL13:
6143 case RENDERPATH_GL11:
6144 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6146 // apply a color tint to the whole view
6147 R_ResetViewRendering2D();
6148 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6149 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6150 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6151 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6152 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6158 matrix4x4_t r_waterscrollmatrix;
6160 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6162 if (r_refdef.fog_density)
6164 r_refdef.fogcolor[0] = r_refdef.fog_red;
6165 r_refdef.fogcolor[1] = r_refdef.fog_green;
6166 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6168 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6169 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6170 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6171 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6175 VectorCopy(r_refdef.fogcolor, fogvec);
6176 // color.rgb *= ContrastBoost * SceneBrightness;
6177 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6178 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6179 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6180 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6185 void R_UpdateVariables(void)
6189 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6191 r_refdef.farclip = r_farclip_base.value;
6192 if (r_refdef.scene.worldmodel)
6193 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6194 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6196 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6197 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6198 r_refdef.polygonfactor = 0;
6199 r_refdef.polygonoffset = 0;
6200 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6201 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6203 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6204 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6205 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6206 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6207 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6208 if (FAKELIGHT_ENABLED)
6210 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6212 if (r_showsurfaces.integer)
6214 r_refdef.scene.rtworld = false;
6215 r_refdef.scene.rtworldshadows = false;
6216 r_refdef.scene.rtdlight = false;
6217 r_refdef.scene.rtdlightshadows = false;
6218 r_refdef.lightmapintensity = 0;
6221 if (gamemode == GAME_NEHAHRA)
6223 if (gl_fogenable.integer)
6225 r_refdef.oldgl_fogenable = true;
6226 r_refdef.fog_density = gl_fogdensity.value;
6227 r_refdef.fog_red = gl_fogred.value;
6228 r_refdef.fog_green = gl_foggreen.value;
6229 r_refdef.fog_blue = gl_fogblue.value;
6230 r_refdef.fog_alpha = 1;
6231 r_refdef.fog_start = 0;
6232 r_refdef.fog_end = gl_skyclip.value;
6233 r_refdef.fog_height = 1<<30;
6234 r_refdef.fog_fadedepth = 128;
6236 else if (r_refdef.oldgl_fogenable)
6238 r_refdef.oldgl_fogenable = false;
6239 r_refdef.fog_density = 0;
6240 r_refdef.fog_red = 0;
6241 r_refdef.fog_green = 0;
6242 r_refdef.fog_blue = 0;
6243 r_refdef.fog_alpha = 0;
6244 r_refdef.fog_start = 0;
6245 r_refdef.fog_end = 0;
6246 r_refdef.fog_height = 1<<30;
6247 r_refdef.fog_fadedepth = 128;
6251 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6252 r_refdef.fog_start = max(0, r_refdef.fog_start);
6253 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6255 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6257 if (r_refdef.fog_density && r_drawfog.integer)
6259 r_refdef.fogenabled = true;
6260 // this is the point where the fog reaches 0.9986 alpha, which we
6261 // consider a good enough cutoff point for the texture
6262 // (0.9986 * 256 == 255.6)
6263 if (r_fog_exp2.integer)
6264 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6266 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6267 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6268 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6269 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6270 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6271 R_BuildFogHeightTexture();
6272 // fog color was already set
6273 // update the fog texture
6274 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)
6275 R_BuildFogTexture();
6276 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6277 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6280 r_refdef.fogenabled = false;
6282 switch(vid.renderpath)
6284 case RENDERPATH_GL20:
6285 case RENDERPATH_D3D9:
6286 case RENDERPATH_D3D10:
6287 case RENDERPATH_D3D11:
6288 case RENDERPATH_SOFT:
6289 case RENDERPATH_GLES2:
6290 if(v_glslgamma.integer && !vid_gammatables_trivial)
6292 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6294 // build GLSL gamma texture
6295 #define RAMPWIDTH 256
6296 unsigned short ramp[RAMPWIDTH * 3];
6297 unsigned char rampbgr[RAMPWIDTH][4];
6300 r_texture_gammaramps_serial = vid_gammatables_serial;
6302 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6303 for(i = 0; i < RAMPWIDTH; ++i)
6305 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6306 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6307 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6310 if (r_texture_gammaramps)
6312 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6316 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6322 // remove GLSL gamma texture
6325 case RENDERPATH_GL13:
6326 case RENDERPATH_GL11:
6331 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6332 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6338 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6339 if( scenetype != r_currentscenetype ) {
6340 // store the old scenetype
6341 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6342 r_currentscenetype = scenetype;
6343 // move in the new scene
6344 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6353 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6355 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6356 if( scenetype == r_currentscenetype ) {
6357 return &r_refdef.scene;
6359 return &r_scenes_store[ scenetype ];
6368 int dpsoftrast_test;
6369 void R_RenderView(void)
6371 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6373 dpsoftrast_test = r_test.integer;
6375 if (r_timereport_active)
6376 R_TimeReport("start");
6377 r_textureframe++; // used only by R_GetCurrentTexture
6378 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6380 if(R_CompileShader_CheckStaticParms())
6383 if (!r_drawentities.integer)
6384 r_refdef.scene.numentities = 0;
6386 R_AnimCache_ClearCache();
6387 R_FrameData_NewFrame();
6389 /* adjust for stereo display */
6390 if(R_Stereo_Active())
6392 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);
6393 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6396 if (r_refdef.view.isoverlay)
6398 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6399 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6400 R_TimeReport("depthclear");
6402 r_refdef.view.showdebug = false;
6404 r_waterstate.enabled = false;
6405 r_waterstate.numwaterplanes = 0;
6409 r_refdef.view.matrix = originalmatrix;
6415 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6417 r_refdef.view.matrix = originalmatrix;
6418 return; //Host_Error ("R_RenderView: NULL worldmodel");
6421 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6423 R_RenderView_UpdateViewVectors();
6425 R_Shadow_UpdateWorldLightSelection();
6427 R_Bloom_StartFrame();
6428 R_Water_StartFrame();
6431 if (r_timereport_active)
6432 R_TimeReport("viewsetup");
6434 R_ResetViewRendering3D();
6436 if (r_refdef.view.clear || r_refdef.fogenabled)
6438 R_ClearScreen(r_refdef.fogenabled);
6439 if (r_timereport_active)
6440 R_TimeReport("viewclear");
6442 r_refdef.view.clear = true;
6444 // this produces a bloom texture to be used in R_BlendView() later
6445 if (r_hdr.integer && r_bloomstate.bloomwidth)
6447 R_HDR_RenderBloomTexture();
6448 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6449 r_textureframe++; // used only by R_GetCurrentTexture
6452 r_refdef.view.showdebug = true;
6455 if (r_timereport_active)
6456 R_TimeReport("visibility");
6458 r_waterstate.numwaterplanes = 0;
6459 if (r_waterstate.enabled)
6460 R_RenderWaterPlanes();
6463 r_waterstate.numwaterplanes = 0;
6466 if (r_timereport_active)
6467 R_TimeReport("blendview");
6469 GL_Scissor(0, 0, vid.width, vid.height);
6470 GL_ScissorTest(false);
6472 r_refdef.view.matrix = originalmatrix;
6477 void R_RenderWaterPlanes(void)
6479 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6481 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6482 if (r_timereport_active)
6483 R_TimeReport("waterworld");
6486 // don't let sound skip if going slow
6487 if (r_refdef.scene.extraupdate)
6490 R_DrawModelsAddWaterPlanes();
6491 if (r_timereport_active)
6492 R_TimeReport("watermodels");
6494 if (r_waterstate.numwaterplanes)
6496 R_Water_ProcessPlanes();
6497 if (r_timereport_active)
6498 R_TimeReport("waterscenes");
6502 extern void R_DrawLightningBeams (void);
6503 extern void VM_CL_AddPolygonsToMeshQueue (void);
6504 extern void R_DrawPortals (void);
6505 extern cvar_t cl_locs_show;
6506 static void R_DrawLocs(void);
6507 static void R_DrawEntityBBoxes(void);
6508 static void R_DrawModelDecals(void);
6509 extern void R_DrawModelShadows(void);
6510 extern void R_DrawModelShadowMaps(void);
6511 extern cvar_t cl_decals_newsystem;
6512 extern qboolean r_shadow_usingdeferredprepass;
6513 void R_RenderScene(void)
6515 qboolean shadowmapping = false;
6517 if (r_timereport_active)
6518 R_TimeReport("beginscene");
6520 r_refdef.stats.renders++;
6524 // don't let sound skip if going slow
6525 if (r_refdef.scene.extraupdate)
6528 R_MeshQueue_BeginScene();
6532 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);
6534 if (r_timereport_active)
6535 R_TimeReport("skystartframe");
6537 if (cl.csqc_vidvars.drawworld)
6539 // don't let sound skip if going slow
6540 if (r_refdef.scene.extraupdate)
6543 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6545 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6546 if (r_timereport_active)
6547 R_TimeReport("worldsky");
6550 if (R_DrawBrushModelsSky() && r_timereport_active)
6551 R_TimeReport("bmodelsky");
6553 if (skyrendermasked && skyrenderlater)
6555 // we have to force off the water clipping plane while rendering sky
6559 if (r_timereport_active)
6560 R_TimeReport("sky");
6564 R_AnimCache_CacheVisibleEntities();
6565 if (r_timereport_active)
6566 R_TimeReport("animation");
6568 R_Shadow_PrepareLights();
6569 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6570 R_Shadow_PrepareModelShadows();
6571 if (r_timereport_active)
6572 R_TimeReport("preparelights");
6574 if (R_Shadow_ShadowMappingEnabled())
6575 shadowmapping = true;
6577 if (r_shadow_usingdeferredprepass)
6578 R_Shadow_DrawPrepass();
6580 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6582 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6583 if (r_timereport_active)
6584 R_TimeReport("worlddepth");
6586 if (r_depthfirst.integer >= 2)
6588 R_DrawModelsDepth();
6589 if (r_timereport_active)
6590 R_TimeReport("modeldepth");
6593 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6595 R_DrawModelShadowMaps();
6596 R_ResetViewRendering3D();
6597 // don't let sound skip if going slow
6598 if (r_refdef.scene.extraupdate)
6602 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6604 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6605 if (r_timereport_active)
6606 R_TimeReport("world");
6609 // don't let sound skip if going slow
6610 if (r_refdef.scene.extraupdate)
6614 if (r_timereport_active)
6615 R_TimeReport("models");
6617 // don't let sound skip if going slow
6618 if (r_refdef.scene.extraupdate)
6621 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6623 R_DrawModelShadows();
6624 R_ResetViewRendering3D();
6625 // don't let sound skip if going slow
6626 if (r_refdef.scene.extraupdate)
6630 if (!r_shadow_usingdeferredprepass)
6632 R_Shadow_DrawLights();
6633 if (r_timereport_active)
6634 R_TimeReport("rtlights");
6637 // don't let sound skip if going slow
6638 if (r_refdef.scene.extraupdate)
6641 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6643 R_DrawModelShadows();
6644 R_ResetViewRendering3D();
6645 // don't let sound skip if going slow
6646 if (r_refdef.scene.extraupdate)
6650 if (cl.csqc_vidvars.drawworld)
6652 if (cl_decals_newsystem.integer)
6654 R_DrawModelDecals();
6655 if (r_timereport_active)
6656 R_TimeReport("modeldecals");
6661 if (r_timereport_active)
6662 R_TimeReport("decals");
6666 if (r_timereport_active)
6667 R_TimeReport("particles");
6670 if (r_timereport_active)
6671 R_TimeReport("explosions");
6673 R_DrawLightningBeams();
6674 if (r_timereport_active)
6675 R_TimeReport("lightning");
6678 VM_CL_AddPolygonsToMeshQueue();
6680 if (r_refdef.view.showdebug)
6682 if (cl_locs_show.integer)
6685 if (r_timereport_active)
6686 R_TimeReport("showlocs");
6689 if (r_drawportals.integer)
6692 if (r_timereport_active)
6693 R_TimeReport("portals");
6696 if (r_showbboxes.value > 0)
6698 R_DrawEntityBBoxes();
6699 if (r_timereport_active)
6700 R_TimeReport("bboxes");
6704 R_MeshQueue_RenderTransparent();
6705 if (r_timereport_active)
6706 R_TimeReport("drawtrans");
6708 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))
6710 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6711 if (r_timereport_active)
6712 R_TimeReport("worlddebug");
6713 R_DrawModelsDebug();
6714 if (r_timereport_active)
6715 R_TimeReport("modeldebug");
6718 if (cl.csqc_vidvars.drawworld)
6720 R_Shadow_DrawCoronas();
6721 if (r_timereport_active)
6722 R_TimeReport("coronas");
6727 GL_DepthTest(false);
6728 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6729 GL_Color(1, 1, 1, 1);
6730 qglBegin(GL_POLYGON);
6731 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6732 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6733 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6734 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6736 qglBegin(GL_POLYGON);
6737 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]);
6738 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]);
6739 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]);
6740 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]);
6742 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6746 // don't let sound skip if going slow
6747 if (r_refdef.scene.extraupdate)
6750 R_ResetViewRendering2D();
6753 static const unsigned short bboxelements[36] =
6763 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6766 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6768 RSurf_ActiveWorldEntity();
6770 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6771 GL_DepthMask(false);
6772 GL_DepthRange(0, 1);
6773 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6774 // R_Mesh_ResetTextureState();
6776 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6777 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6778 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6779 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6780 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6781 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6782 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6783 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6784 R_FillColors(color4f, 8, cr, cg, cb, ca);
6785 if (r_refdef.fogenabled)
6787 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6789 f1 = RSurf_FogVertex(v);
6791 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6792 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6793 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6796 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6797 R_Mesh_ResetTextureState();
6798 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6799 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6802 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6806 prvm_edict_t *edict;
6807 prvm_prog_t *prog_save = prog;
6809 // this function draws bounding boxes of server entities
6813 GL_CullFace(GL_NONE);
6814 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6818 for (i = 0;i < numsurfaces;i++)
6820 edict = PRVM_EDICT_NUM(surfacelist[i]);
6821 switch ((int)edict->fields.server->solid)
6823 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6824 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6825 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6826 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6827 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6828 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6830 color[3] *= r_showbboxes.value;
6831 color[3] = bound(0, color[3], 1);
6832 GL_DepthTest(!r_showdisabledepthtest.integer);
6833 GL_CullFace(r_refdef.view.cullface_front);
6834 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6840 static void R_DrawEntityBBoxes(void)
6843 prvm_edict_t *edict;
6845 prvm_prog_t *prog_save = prog;
6847 // this function draws bounding boxes of server entities
6853 for (i = 0;i < prog->num_edicts;i++)
6855 edict = PRVM_EDICT_NUM(i);
6856 if (edict->priv.server->free)
6858 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6859 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6861 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6863 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6864 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6870 static const int nomodelelement3i[24] =
6882 static const unsigned short nomodelelement3s[24] =
6894 static const float nomodelvertex3f[6*3] =
6904 static const float nomodelcolor4f[6*4] =
6906 0.0f, 0.0f, 0.5f, 1.0f,
6907 0.0f, 0.0f, 0.5f, 1.0f,
6908 0.0f, 0.5f, 0.0f, 1.0f,
6909 0.0f, 0.5f, 0.0f, 1.0f,
6910 0.5f, 0.0f, 0.0f, 1.0f,
6911 0.5f, 0.0f, 0.0f, 1.0f
6914 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6920 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);
6922 // this is only called once per entity so numsurfaces is always 1, and
6923 // surfacelist is always {0}, so this code does not handle batches
6925 if (rsurface.ent_flags & RENDER_ADDITIVE)
6927 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6928 GL_DepthMask(false);
6930 else if (rsurface.colormod[3] < 1)
6932 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6933 GL_DepthMask(false);
6937 GL_BlendFunc(GL_ONE, GL_ZERO);
6940 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6941 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6942 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6943 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6944 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6945 for (i = 0, c = color4f;i < 6;i++, c += 4)
6947 c[0] *= rsurface.colormod[0];
6948 c[1] *= rsurface.colormod[1];
6949 c[2] *= rsurface.colormod[2];
6950 c[3] *= rsurface.colormod[3];
6952 if (r_refdef.fogenabled)
6954 for (i = 0, c = color4f;i < 6;i++, c += 4)
6956 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6958 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6959 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6960 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6963 // R_Mesh_ResetTextureState();
6964 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6965 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6966 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6969 void R_DrawNoModel(entity_render_t *ent)
6972 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6973 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6974 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6976 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6979 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6981 vec3_t right1, right2, diff, normal;
6983 VectorSubtract (org2, org1, normal);
6985 // calculate 'right' vector for start
6986 VectorSubtract (r_refdef.view.origin, org1, diff);
6987 CrossProduct (normal, diff, right1);
6988 VectorNormalize (right1);
6990 // calculate 'right' vector for end
6991 VectorSubtract (r_refdef.view.origin, org2, diff);
6992 CrossProduct (normal, diff, right2);
6993 VectorNormalize (right2);
6995 vert[ 0] = org1[0] + width * right1[0];
6996 vert[ 1] = org1[1] + width * right1[1];
6997 vert[ 2] = org1[2] + width * right1[2];
6998 vert[ 3] = org1[0] - width * right1[0];
6999 vert[ 4] = org1[1] - width * right1[1];
7000 vert[ 5] = org1[2] - width * right1[2];
7001 vert[ 6] = org2[0] - width * right2[0];
7002 vert[ 7] = org2[1] - width * right2[1];
7003 vert[ 8] = org2[2] - width * right2[2];
7004 vert[ 9] = org2[0] + width * right2[0];
7005 vert[10] = org2[1] + width * right2[1];
7006 vert[11] = org2[2] + width * right2[2];
7009 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)
7011 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7012 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7013 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7014 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7015 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7016 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7017 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7018 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7019 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7020 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7021 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7022 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7025 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7030 VectorSet(v, x, y, z);
7031 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7032 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7034 if (i == mesh->numvertices)
7036 if (mesh->numvertices < mesh->maxvertices)
7038 VectorCopy(v, vertex3f);
7039 mesh->numvertices++;
7041 return mesh->numvertices;
7047 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7051 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7052 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7053 e = mesh->element3i + mesh->numtriangles * 3;
7054 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7056 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7057 if (mesh->numtriangles < mesh->maxtriangles)
7062 mesh->numtriangles++;
7064 element[1] = element[2];
7068 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7072 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7073 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7074 e = mesh->element3i + mesh->numtriangles * 3;
7075 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7077 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7078 if (mesh->numtriangles < mesh->maxtriangles)
7083 mesh->numtriangles++;
7085 element[1] = element[2];
7089 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7090 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7092 int planenum, planenum2;
7095 mplane_t *plane, *plane2;
7097 double temppoints[2][256*3];
7098 // figure out how large a bounding box we need to properly compute this brush
7100 for (w = 0;w < numplanes;w++)
7101 maxdist = max(maxdist, fabs(planes[w].dist));
7102 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7103 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7104 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7108 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7109 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7111 if (planenum2 == planenum)
7113 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);
7116 if (tempnumpoints < 3)
7118 // generate elements forming a triangle fan for this polygon
7119 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7123 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)
7125 texturelayer_t *layer;
7126 layer = t->currentlayers + t->currentnumlayers++;
7128 layer->depthmask = depthmask;
7129 layer->blendfunc1 = blendfunc1;
7130 layer->blendfunc2 = blendfunc2;
7131 layer->texture = texture;
7132 layer->texmatrix = *matrix;
7133 layer->color[0] = r;
7134 layer->color[1] = g;
7135 layer->color[2] = b;
7136 layer->color[3] = a;
7139 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7141 if(parms[0] == 0 && parms[1] == 0)
7143 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7144 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7149 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7152 index = parms[2] + r_refdef.scene.time * parms[3];
7153 index -= floor(index);
7154 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7157 case Q3WAVEFUNC_NONE:
7158 case Q3WAVEFUNC_NOISE:
7159 case Q3WAVEFUNC_COUNT:
7162 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7163 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7164 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7165 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7166 case Q3WAVEFUNC_TRIANGLE:
7168 f = index - floor(index);
7179 f = parms[0] + parms[1] * f;
7180 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7181 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7185 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7190 matrix4x4_t matrix, temp;
7191 switch(tcmod->tcmod)
7195 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7196 matrix = r_waterscrollmatrix;
7198 matrix = identitymatrix;
7200 case Q3TCMOD_ENTITYTRANSLATE:
7201 // this is used in Q3 to allow the gamecode to control texcoord
7202 // scrolling on the entity, which is not supported in darkplaces yet.
7203 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7205 case Q3TCMOD_ROTATE:
7206 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7207 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7208 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7211 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7213 case Q3TCMOD_SCROLL:
7214 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7216 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7217 w = (int) tcmod->parms[0];
7218 h = (int) tcmod->parms[1];
7219 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7221 idx = (int) floor(f * w * h);
7222 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7224 case Q3TCMOD_STRETCH:
7225 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7226 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7228 case Q3TCMOD_TRANSFORM:
7229 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7230 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7231 VectorSet(tcmat + 6, 0 , 0 , 1);
7232 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7233 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7235 case Q3TCMOD_TURBULENT:
7236 // this is handled in the RSurf_PrepareVertices function
7237 matrix = identitymatrix;
7241 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7244 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7246 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7247 char name[MAX_QPATH];
7248 skinframe_t *skinframe;
7249 unsigned char pixels[296*194];
7250 strlcpy(cache->name, skinname, sizeof(cache->name));
7251 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7252 if (developer_loading.integer)
7253 Con_Printf("loading %s\n", name);
7254 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7255 if (!skinframe || !skinframe->base)
7258 fs_offset_t filesize;
7260 f = FS_LoadFile(name, tempmempool, true, &filesize);
7263 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7264 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7268 cache->skinframe = skinframe;
7271 texture_t *R_GetCurrentTexture(texture_t *t)
7274 const entity_render_t *ent = rsurface.entity;
7275 dp_model_t *model = ent->model;
7276 q3shaderinfo_layer_tcmod_t *tcmod;
7278 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7279 return t->currentframe;
7280 t->update_lastrenderframe = r_textureframe;
7281 t->update_lastrenderentity = (void *)ent;
7283 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7284 t->camera_entity = ent->entitynumber;
7286 t->camera_entity = 0;
7288 // switch to an alternate material if this is a q1bsp animated material
7290 texture_t *texture = t;
7291 int s = rsurface.ent_skinnum;
7292 if ((unsigned int)s >= (unsigned int)model->numskins)
7294 if (model->skinscenes)
7296 if (model->skinscenes[s].framecount > 1)
7297 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7299 s = model->skinscenes[s].firstframe;
7302 t = t + s * model->num_surfaces;
7305 // use an alternate animation if the entity's frame is not 0,
7306 // and only if the texture has an alternate animation
7307 if (rsurface.ent_alttextures && t->anim_total[1])
7308 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7310 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7312 texture->currentframe = t;
7315 // update currentskinframe to be a qw skin or animation frame
7316 if (rsurface.ent_qwskin >= 0)
7318 i = rsurface.ent_qwskin;
7319 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7321 r_qwskincache_size = cl.maxclients;
7323 Mem_Free(r_qwskincache);
7324 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7326 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7327 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7328 t->currentskinframe = r_qwskincache[i].skinframe;
7329 if (t->currentskinframe == NULL)
7330 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7332 else if (t->numskinframes >= 2)
7333 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7334 if (t->backgroundnumskinframes >= 2)
7335 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7337 t->currentmaterialflags = t->basematerialflags;
7338 t->currentalpha = rsurface.colormod[3];
7339 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7340 t->currentalpha *= r_wateralpha.value;
7341 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7342 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7343 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7344 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7345 if (!(rsurface.ent_flags & RENDER_LIGHT))
7346 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7347 else if (FAKELIGHT_ENABLED)
7349 // no modellight if using fakelight for the map
7351 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7353 // pick a model lighting mode
7354 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7355 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7357 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7359 if (rsurface.ent_flags & RENDER_ADDITIVE)
7360 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7361 else if (t->currentalpha < 1)
7362 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7363 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7364 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7365 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7366 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7367 if (t->backgroundnumskinframes)
7368 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7369 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7371 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7372 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7375 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7376 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7377 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7379 // there is no tcmod
7380 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7382 t->currenttexmatrix = r_waterscrollmatrix;
7383 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7385 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7387 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7388 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7391 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7392 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7393 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7394 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7396 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7397 if (t->currentskinframe->qpixels)
7398 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7399 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7400 if (!t->basetexture)
7401 t->basetexture = r_texture_notexture;
7402 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7403 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7404 t->nmaptexture = t->currentskinframe->nmap;
7405 if (!t->nmaptexture)
7406 t->nmaptexture = r_texture_blanknormalmap;
7407 t->glosstexture = r_texture_black;
7408 t->glowtexture = t->currentskinframe->glow;
7409 t->fogtexture = t->currentskinframe->fog;
7410 t->reflectmasktexture = t->currentskinframe->reflect;
7411 if (t->backgroundnumskinframes)
7413 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7414 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7415 t->backgroundglosstexture = r_texture_black;
7416 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7417 if (!t->backgroundnmaptexture)
7418 t->backgroundnmaptexture = r_texture_blanknormalmap;
7422 t->backgroundbasetexture = r_texture_white;
7423 t->backgroundnmaptexture = r_texture_blanknormalmap;
7424 t->backgroundglosstexture = r_texture_black;
7425 t->backgroundglowtexture = NULL;
7427 t->specularpower = r_shadow_glossexponent.value;
7428 // TODO: store reference values for these in the texture?
7429 t->specularscale = 0;
7430 if (r_shadow_gloss.integer > 0)
7432 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7434 if (r_shadow_glossintensity.value > 0)
7436 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7437 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7438 t->specularscale = r_shadow_glossintensity.value;
7441 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7443 t->glosstexture = r_texture_white;
7444 t->backgroundglosstexture = r_texture_white;
7445 t->specularscale = r_shadow_gloss2intensity.value;
7446 t->specularpower = r_shadow_gloss2exponent.value;
7449 t->specularscale *= t->specularscalemod;
7450 t->specularpower *= t->specularpowermod;
7452 // lightmaps mode looks bad with dlights using actual texturing, so turn
7453 // off the colormap and glossmap, but leave the normalmap on as it still
7454 // accurately represents the shading involved
7455 if (gl_lightmaps.integer)
7457 t->basetexture = r_texture_grey128;
7458 t->pantstexture = r_texture_black;
7459 t->shirttexture = r_texture_black;
7460 t->nmaptexture = r_texture_blanknormalmap;
7461 t->glosstexture = r_texture_black;
7462 t->glowtexture = NULL;
7463 t->fogtexture = NULL;
7464 t->reflectmasktexture = NULL;
7465 t->backgroundbasetexture = NULL;
7466 t->backgroundnmaptexture = r_texture_blanknormalmap;
7467 t->backgroundglosstexture = r_texture_black;
7468 t->backgroundglowtexture = NULL;
7469 t->specularscale = 0;
7470 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7473 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7474 VectorClear(t->dlightcolor);
7475 t->currentnumlayers = 0;
7476 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7478 int blendfunc1, blendfunc2;
7480 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7482 blendfunc1 = GL_SRC_ALPHA;
7483 blendfunc2 = GL_ONE;
7485 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7487 blendfunc1 = GL_SRC_ALPHA;
7488 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7490 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7492 blendfunc1 = t->customblendfunc[0];
7493 blendfunc2 = t->customblendfunc[1];
7497 blendfunc1 = GL_ONE;
7498 blendfunc2 = GL_ZERO;
7500 // don't colormod evilblend textures
7501 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7502 VectorSet(t->lightmapcolor, 1, 1, 1);
7503 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7504 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7506 // fullbright is not affected by r_refdef.lightmapintensity
7507 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]);
7508 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7509 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]);
7510 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7511 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]);
7515 vec3_t ambientcolor;
7517 // set the color tint used for lights affecting this surface
7518 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7520 // q3bsp has no lightmap updates, so the lightstylevalue that
7521 // would normally be baked into the lightmap must be
7522 // applied to the color
7523 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7524 if (model->type == mod_brushq3)
7525 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7526 colorscale *= r_refdef.lightmapintensity;
7527 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7528 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7529 // basic lit geometry
7530 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]);
7531 // add pants/shirt if needed
7532 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7533 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]);
7534 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7535 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]);
7536 // now add ambient passes if needed
7537 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7539 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]);
7540 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7541 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]);
7542 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7543 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]);
7546 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7547 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]);
7548 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7550 // if this is opaque use alpha blend which will darken the earlier
7553 // if this is an alpha blended material, all the earlier passes
7554 // were darkened by fog already, so we only need to add the fog
7555 // color ontop through the fog mask texture
7557 // if this is an additive blended material, all the earlier passes
7558 // were darkened by fog already, and we should not add fog color
7559 // (because the background was not darkened, there is no fog color
7560 // that was lost behind it).
7561 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]);
7565 return t->currentframe;
7568 rsurfacestate_t rsurface;
7570 void RSurf_ActiveWorldEntity(void)
7572 dp_model_t *model = r_refdef.scene.worldmodel;
7573 //if (rsurface.entity == r_refdef.scene.worldentity)
7575 rsurface.entity = r_refdef.scene.worldentity;
7576 rsurface.skeleton = NULL;
7577 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7578 rsurface.ent_skinnum = 0;
7579 rsurface.ent_qwskin = -1;
7580 rsurface.ent_shadertime = 0;
7581 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7582 rsurface.matrix = identitymatrix;
7583 rsurface.inversematrix = identitymatrix;
7584 rsurface.matrixscale = 1;
7585 rsurface.inversematrixscale = 1;
7586 R_EntityMatrix(&identitymatrix);
7587 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7588 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7589 rsurface.fograngerecip = r_refdef.fograngerecip;
7590 rsurface.fogheightfade = r_refdef.fogheightfade;
7591 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7592 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7593 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7594 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7595 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7596 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7597 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7598 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7599 rsurface.colormod[3] = 1;
7600 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);
7601 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7602 rsurface.frameblend[0].lerp = 1;
7603 rsurface.ent_alttextures = false;
7604 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7605 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7606 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7607 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7608 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7609 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7610 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7611 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7612 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7613 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7614 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7615 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7616 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7617 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7618 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7619 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7620 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7621 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7622 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7623 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7624 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7625 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7627 rsurface.modelelement3i = model->surfmesh.data_element3i;
7628 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7629 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7630 rsurface.modelelement3s = model->surfmesh.data_element3s;
7631 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7632 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7633 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7634 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7635 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7636 rsurface.modelsurfaces = model->data_surfaces;
7637 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7638 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7639 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7640 rsurface.modelgeneratedvertex = false;
7641 rsurface.batchgeneratedvertex = false;
7642 rsurface.batchfirstvertex = 0;
7643 rsurface.batchnumvertices = 0;
7644 rsurface.batchfirsttriangle = 0;
7645 rsurface.batchnumtriangles = 0;
7646 rsurface.batchvertex3f = NULL;
7647 rsurface.batchvertex3f_vertexbuffer = NULL;
7648 rsurface.batchvertex3f_bufferoffset = 0;
7649 rsurface.batchsvector3f = NULL;
7650 rsurface.batchsvector3f_vertexbuffer = NULL;
7651 rsurface.batchsvector3f_bufferoffset = 0;
7652 rsurface.batchtvector3f = NULL;
7653 rsurface.batchtvector3f_vertexbuffer = NULL;
7654 rsurface.batchtvector3f_bufferoffset = 0;
7655 rsurface.batchnormal3f = NULL;
7656 rsurface.batchnormal3f_vertexbuffer = NULL;
7657 rsurface.batchnormal3f_bufferoffset = 0;
7658 rsurface.batchlightmapcolor4f = NULL;
7659 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7660 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7661 rsurface.batchtexcoordtexture2f = NULL;
7662 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7663 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7664 rsurface.batchtexcoordlightmap2f = NULL;
7665 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7666 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7667 rsurface.batchvertexmesh = NULL;
7668 rsurface.batchvertexmeshbuffer = NULL;
7669 rsurface.batchvertex3fbuffer = NULL;
7670 rsurface.batchelement3i = NULL;
7671 rsurface.batchelement3i_indexbuffer = NULL;
7672 rsurface.batchelement3i_bufferoffset = 0;
7673 rsurface.batchelement3s = NULL;
7674 rsurface.batchelement3s_indexbuffer = NULL;
7675 rsurface.batchelement3s_bufferoffset = 0;
7676 rsurface.passcolor4f = NULL;
7677 rsurface.passcolor4f_vertexbuffer = NULL;
7678 rsurface.passcolor4f_bufferoffset = 0;
7681 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7683 dp_model_t *model = ent->model;
7684 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7686 rsurface.entity = (entity_render_t *)ent;
7687 rsurface.skeleton = ent->skeleton;
7688 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7689 rsurface.ent_skinnum = ent->skinnum;
7690 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;
7691 rsurface.ent_shadertime = ent->shadertime;
7692 rsurface.ent_flags = ent->flags;
7693 rsurface.matrix = ent->matrix;
7694 rsurface.inversematrix = ent->inversematrix;
7695 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7696 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7697 R_EntityMatrix(&rsurface.matrix);
7698 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7699 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7700 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7701 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7702 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7703 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7704 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7705 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7706 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7707 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7708 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7709 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7710 rsurface.colormod[3] = ent->alpha;
7711 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7712 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7713 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7714 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7715 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7716 if (ent->model->brush.submodel && !prepass)
7718 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7719 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7721 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7723 if (ent->animcache_vertex3f)
7725 rsurface.modelvertex3f = ent->animcache_vertex3f;
7726 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7727 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7728 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7729 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7730 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7731 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7733 else if (wanttangents)
7735 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7736 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7737 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7738 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7739 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7740 rsurface.modelvertexmesh = NULL;
7741 rsurface.modelvertexmeshbuffer = NULL;
7742 rsurface.modelvertex3fbuffer = NULL;
7744 else if (wantnormals)
7746 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7747 rsurface.modelsvector3f = NULL;
7748 rsurface.modeltvector3f = NULL;
7749 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7750 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7751 rsurface.modelvertexmesh = NULL;
7752 rsurface.modelvertexmeshbuffer = NULL;
7753 rsurface.modelvertex3fbuffer = NULL;
7757 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7758 rsurface.modelsvector3f = NULL;
7759 rsurface.modeltvector3f = NULL;
7760 rsurface.modelnormal3f = NULL;
7761 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7762 rsurface.modelvertexmesh = NULL;
7763 rsurface.modelvertexmeshbuffer = NULL;
7764 rsurface.modelvertex3fbuffer = NULL;
7766 rsurface.modelvertex3f_vertexbuffer = 0;
7767 rsurface.modelvertex3f_bufferoffset = 0;
7768 rsurface.modelsvector3f_vertexbuffer = 0;
7769 rsurface.modelsvector3f_bufferoffset = 0;
7770 rsurface.modeltvector3f_vertexbuffer = 0;
7771 rsurface.modeltvector3f_bufferoffset = 0;
7772 rsurface.modelnormal3f_vertexbuffer = 0;
7773 rsurface.modelnormal3f_bufferoffset = 0;
7774 rsurface.modelgeneratedvertex = true;
7778 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7779 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7780 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7781 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7782 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7783 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7784 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7785 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7787 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7788 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7789 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7790 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7791 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7792 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7793 rsurface.modelgeneratedvertex = false;
7795 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7796 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7797 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7798 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7799 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7800 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7801 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7802 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7804 rsurface.modelelement3i = model->surfmesh.data_element3i;
7805 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7806 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7807 rsurface.modelelement3s = model->surfmesh.data_element3s;
7808 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7809 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7810 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7811 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7812 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7813 rsurface.modelsurfaces = model->data_surfaces;
7814 rsurface.batchgeneratedvertex = false;
7815 rsurface.batchfirstvertex = 0;
7816 rsurface.batchnumvertices = 0;
7817 rsurface.batchfirsttriangle = 0;
7818 rsurface.batchnumtriangles = 0;
7819 rsurface.batchvertex3f = NULL;
7820 rsurface.batchvertex3f_vertexbuffer = NULL;
7821 rsurface.batchvertex3f_bufferoffset = 0;
7822 rsurface.batchsvector3f = NULL;
7823 rsurface.batchsvector3f_vertexbuffer = NULL;
7824 rsurface.batchsvector3f_bufferoffset = 0;
7825 rsurface.batchtvector3f = NULL;
7826 rsurface.batchtvector3f_vertexbuffer = NULL;
7827 rsurface.batchtvector3f_bufferoffset = 0;
7828 rsurface.batchnormal3f = NULL;
7829 rsurface.batchnormal3f_vertexbuffer = NULL;
7830 rsurface.batchnormal3f_bufferoffset = 0;
7831 rsurface.batchlightmapcolor4f = NULL;
7832 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7833 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7834 rsurface.batchtexcoordtexture2f = NULL;
7835 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7836 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7837 rsurface.batchtexcoordlightmap2f = NULL;
7838 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7839 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7840 rsurface.batchvertexmesh = NULL;
7841 rsurface.batchvertexmeshbuffer = NULL;
7842 rsurface.batchvertex3fbuffer = NULL;
7843 rsurface.batchelement3i = NULL;
7844 rsurface.batchelement3i_indexbuffer = NULL;
7845 rsurface.batchelement3i_bufferoffset = 0;
7846 rsurface.batchelement3s = NULL;
7847 rsurface.batchelement3s_indexbuffer = NULL;
7848 rsurface.batchelement3s_bufferoffset = 0;
7849 rsurface.passcolor4f = NULL;
7850 rsurface.passcolor4f_vertexbuffer = NULL;
7851 rsurface.passcolor4f_bufferoffset = 0;
7854 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)
7856 rsurface.entity = r_refdef.scene.worldentity;
7857 rsurface.skeleton = NULL;
7858 rsurface.ent_skinnum = 0;
7859 rsurface.ent_qwskin = -1;
7860 rsurface.ent_shadertime = shadertime;
7861 rsurface.ent_flags = entflags;
7862 rsurface.modelnumvertices = numvertices;
7863 rsurface.modelnumtriangles = numtriangles;
7864 rsurface.matrix = *matrix;
7865 rsurface.inversematrix = *inversematrix;
7866 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7867 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7868 R_EntityMatrix(&rsurface.matrix);
7869 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7870 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7871 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7872 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7873 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7874 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7875 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7876 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7877 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7878 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7879 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7880 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7881 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);
7882 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7883 rsurface.frameblend[0].lerp = 1;
7884 rsurface.ent_alttextures = false;
7885 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7886 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7889 rsurface.modelvertex3f = (float *)vertex3f;
7890 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7891 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7892 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7894 else if (wantnormals)
7896 rsurface.modelvertex3f = (float *)vertex3f;
7897 rsurface.modelsvector3f = NULL;
7898 rsurface.modeltvector3f = NULL;
7899 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7903 rsurface.modelvertex3f = (float *)vertex3f;
7904 rsurface.modelsvector3f = NULL;
7905 rsurface.modeltvector3f = NULL;
7906 rsurface.modelnormal3f = NULL;
7908 rsurface.modelvertexmesh = NULL;
7909 rsurface.modelvertexmeshbuffer = NULL;
7910 rsurface.modelvertex3fbuffer = NULL;
7911 rsurface.modelvertex3f_vertexbuffer = 0;
7912 rsurface.modelvertex3f_bufferoffset = 0;
7913 rsurface.modelsvector3f_vertexbuffer = 0;
7914 rsurface.modelsvector3f_bufferoffset = 0;
7915 rsurface.modeltvector3f_vertexbuffer = 0;
7916 rsurface.modeltvector3f_bufferoffset = 0;
7917 rsurface.modelnormal3f_vertexbuffer = 0;
7918 rsurface.modelnormal3f_bufferoffset = 0;
7919 rsurface.modelgeneratedvertex = true;
7920 rsurface.modellightmapcolor4f = (float *)color4f;
7921 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7922 rsurface.modellightmapcolor4f_bufferoffset = 0;
7923 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7924 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7925 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7926 rsurface.modeltexcoordlightmap2f = NULL;
7927 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7928 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7929 rsurface.modelelement3i = (int *)element3i;
7930 rsurface.modelelement3i_indexbuffer = NULL;
7931 rsurface.modelelement3i_bufferoffset = 0;
7932 rsurface.modelelement3s = (unsigned short *)element3s;
7933 rsurface.modelelement3s_indexbuffer = NULL;
7934 rsurface.modelelement3s_bufferoffset = 0;
7935 rsurface.modellightmapoffsets = NULL;
7936 rsurface.modelsurfaces = NULL;
7937 rsurface.batchgeneratedvertex = false;
7938 rsurface.batchfirstvertex = 0;
7939 rsurface.batchnumvertices = 0;
7940 rsurface.batchfirsttriangle = 0;
7941 rsurface.batchnumtriangles = 0;
7942 rsurface.batchvertex3f = NULL;
7943 rsurface.batchvertex3f_vertexbuffer = NULL;
7944 rsurface.batchvertex3f_bufferoffset = 0;
7945 rsurface.batchsvector3f = NULL;
7946 rsurface.batchsvector3f_vertexbuffer = NULL;
7947 rsurface.batchsvector3f_bufferoffset = 0;
7948 rsurface.batchtvector3f = NULL;
7949 rsurface.batchtvector3f_vertexbuffer = NULL;
7950 rsurface.batchtvector3f_bufferoffset = 0;
7951 rsurface.batchnormal3f = NULL;
7952 rsurface.batchnormal3f_vertexbuffer = NULL;
7953 rsurface.batchnormal3f_bufferoffset = 0;
7954 rsurface.batchlightmapcolor4f = NULL;
7955 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7956 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7957 rsurface.batchtexcoordtexture2f = NULL;
7958 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7959 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7960 rsurface.batchtexcoordlightmap2f = NULL;
7961 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7962 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7963 rsurface.batchvertexmesh = NULL;
7964 rsurface.batchvertexmeshbuffer = NULL;
7965 rsurface.batchvertex3fbuffer = NULL;
7966 rsurface.batchelement3i = NULL;
7967 rsurface.batchelement3i_indexbuffer = NULL;
7968 rsurface.batchelement3i_bufferoffset = 0;
7969 rsurface.batchelement3s = NULL;
7970 rsurface.batchelement3s_indexbuffer = NULL;
7971 rsurface.batchelement3s_bufferoffset = 0;
7972 rsurface.passcolor4f = NULL;
7973 rsurface.passcolor4f_vertexbuffer = NULL;
7974 rsurface.passcolor4f_bufferoffset = 0;
7976 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7978 if ((wantnormals || wanttangents) && !normal3f)
7980 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7981 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7983 if (wanttangents && !svector3f)
7985 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7986 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7987 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7992 float RSurf_FogPoint(const float *v)
7994 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7995 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7996 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7997 float FogHeightFade = r_refdef.fogheightfade;
7999 unsigned int fogmasktableindex;
8000 if (r_refdef.fogplaneviewabove)
8001 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8003 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8004 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8005 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8008 float RSurf_FogVertex(const float *v)
8010 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8011 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8012 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8013 float FogHeightFade = rsurface.fogheightfade;
8015 unsigned int fogmasktableindex;
8016 if (r_refdef.fogplaneviewabove)
8017 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8019 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8020 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8021 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8024 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8027 for (i = 0;i < numelements;i++)
8028 outelement3i[i] = inelement3i[i] + adjust;
8031 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8032 extern cvar_t gl_vbo;
8033 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8041 int surfacefirsttriangle;
8042 int surfacenumtriangles;
8043 int surfacefirstvertex;
8044 int surfaceendvertex;
8045 int surfacenumvertices;
8046 int batchnumvertices;
8047 int batchnumtriangles;
8051 qboolean dynamicvertex;
8055 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8057 q3shaderinfo_deform_t *deform;
8058 const msurface_t *surface, *firstsurface;
8059 r_vertexmesh_t *vertexmesh;
8060 if (!texturenumsurfaces)
8062 // find vertex range of this surface batch
8064 firstsurface = texturesurfacelist[0];
8065 firsttriangle = firstsurface->num_firsttriangle;
8066 batchnumvertices = 0;
8067 batchnumtriangles = 0;
8068 firstvertex = endvertex = firstsurface->num_firstvertex;
8069 for (i = 0;i < texturenumsurfaces;i++)
8071 surface = texturesurfacelist[i];
8072 if (surface != firstsurface + i)
8074 surfacefirstvertex = surface->num_firstvertex;
8075 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8076 surfacenumvertices = surface->num_vertices;
8077 surfacenumtriangles = surface->num_triangles;
8078 if (firstvertex > surfacefirstvertex)
8079 firstvertex = surfacefirstvertex;
8080 if (endvertex < surfaceendvertex)
8081 endvertex = surfaceendvertex;
8082 batchnumvertices += surfacenumvertices;
8083 batchnumtriangles += surfacenumtriangles;
8086 // we now know the vertex range used, and if there are any gaps in it
8087 rsurface.batchfirstvertex = firstvertex;
8088 rsurface.batchnumvertices = endvertex - firstvertex;
8089 rsurface.batchfirsttriangle = firsttriangle;
8090 rsurface.batchnumtriangles = batchnumtriangles;
8092 // this variable holds flags for which properties have been updated that
8093 // may require regenerating vertexmesh array...
8096 // check if any dynamic vertex processing must occur
8097 dynamicvertex = false;
8099 // if there is a chance of animated vertex colors, it's a dynamic batch
8100 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8102 dynamicvertex = true;
8103 batchneed |= BATCHNEED_NOGAPS;
8104 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8107 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8109 switch (deform->deform)
8112 case Q3DEFORM_PROJECTIONSHADOW:
8113 case Q3DEFORM_TEXT0:
8114 case Q3DEFORM_TEXT1:
8115 case Q3DEFORM_TEXT2:
8116 case Q3DEFORM_TEXT3:
8117 case Q3DEFORM_TEXT4:
8118 case Q3DEFORM_TEXT5:
8119 case Q3DEFORM_TEXT6:
8120 case Q3DEFORM_TEXT7:
8123 case Q3DEFORM_AUTOSPRITE:
8124 dynamicvertex = true;
8125 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8126 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8128 case Q3DEFORM_AUTOSPRITE2:
8129 dynamicvertex = true;
8130 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8131 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8133 case Q3DEFORM_NORMAL:
8134 dynamicvertex = true;
8135 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8136 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8139 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8140 break; // if wavefunc is a nop, ignore this transform
8141 dynamicvertex = true;
8142 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8143 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8145 case Q3DEFORM_BULGE:
8146 dynamicvertex = true;
8147 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8148 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8151 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8152 break; // if wavefunc is a nop, ignore this transform
8153 dynamicvertex = true;
8154 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8155 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8159 switch(rsurface.texture->tcgen.tcgen)
8162 case Q3TCGEN_TEXTURE:
8164 case Q3TCGEN_LIGHTMAP:
8165 dynamicvertex = true;
8166 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8167 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8169 case Q3TCGEN_VECTOR:
8170 dynamicvertex = true;
8171 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8172 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8174 case Q3TCGEN_ENVIRONMENT:
8175 dynamicvertex = true;
8176 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8177 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8180 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8182 dynamicvertex = true;
8183 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8184 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8187 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8189 dynamicvertex = true;
8190 batchneed |= BATCHNEED_NOGAPS;
8191 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8194 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8196 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8197 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8198 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8199 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8200 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8201 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8202 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8205 // when the model data has no vertex buffer (dynamic mesh), we need to
8207 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8208 batchneed |= BATCHNEED_NOGAPS;
8210 // if needsupdate, we have to do a dynamic vertex batch for sure
8211 if (needsupdate & batchneed)
8212 dynamicvertex = true;
8214 // see if we need to build vertexmesh from arrays
8215 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8216 dynamicvertex = true;
8218 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8219 // also some drivers strongly dislike firstvertex
8220 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8221 dynamicvertex = true;
8223 rsurface.batchvertex3f = rsurface.modelvertex3f;
8224 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8225 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8226 rsurface.batchsvector3f = rsurface.modelsvector3f;
8227 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8228 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8229 rsurface.batchtvector3f = rsurface.modeltvector3f;
8230 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8231 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8232 rsurface.batchnormal3f = rsurface.modelnormal3f;
8233 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8234 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8235 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8236 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8237 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8238 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8239 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8240 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8241 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8242 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8243 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8244 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8245 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8246 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8247 rsurface.batchelement3i = rsurface.modelelement3i;
8248 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8249 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8250 rsurface.batchelement3s = rsurface.modelelement3s;
8251 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8252 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8254 // if any dynamic vertex processing has to occur in software, we copy the
8255 // entire surface list together before processing to rebase the vertices
8256 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8258 // if any gaps exist and we do not have a static vertex buffer, we have to
8259 // copy the surface list together to avoid wasting upload bandwidth on the
8260 // vertices in the gaps.
8262 // if gaps exist and we have a static vertex buffer, we still have to
8263 // combine the index buffer ranges into one dynamic index buffer.
8265 // in all cases we end up with data that can be drawn in one call.
8269 // static vertex data, just set pointers...
8270 rsurface.batchgeneratedvertex = false;
8271 // if there are gaps, we want to build a combined index buffer,
8272 // otherwise use the original static buffer with an appropriate offset
8275 // build a new triangle elements array for this batch
8276 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8277 rsurface.batchfirsttriangle = 0;
8279 for (i = 0;i < texturenumsurfaces;i++)
8281 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8282 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8283 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8284 numtriangles += surfacenumtriangles;
8286 rsurface.batchelement3i_indexbuffer = NULL;
8287 rsurface.batchelement3i_bufferoffset = 0;
8288 rsurface.batchelement3s = NULL;
8289 rsurface.batchelement3s_indexbuffer = NULL;
8290 rsurface.batchelement3s_bufferoffset = 0;
8291 if (endvertex <= 65536)
8293 // make a 16bit (unsigned short) index array if possible
8294 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8295 for (i = 0;i < numtriangles*3;i++)
8296 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8302 // something needs software processing, do it for real...
8303 // we only directly handle separate array data in this case and then
8304 // generate interleaved data if needed...
8305 rsurface.batchgeneratedvertex = true;
8307 // now copy the vertex data into a combined array and make an index array
8308 // (this is what Quake3 does all the time)
8309 //if (gaps || rsurface.batchfirstvertex)
8311 rsurface.batchvertex3fbuffer = NULL;
8312 rsurface.batchvertexmesh = NULL;
8313 rsurface.batchvertexmeshbuffer = NULL;
8314 rsurface.batchvertex3f = NULL;
8315 rsurface.batchvertex3f_vertexbuffer = NULL;
8316 rsurface.batchvertex3f_bufferoffset = 0;
8317 rsurface.batchsvector3f = NULL;
8318 rsurface.batchsvector3f_vertexbuffer = NULL;
8319 rsurface.batchsvector3f_bufferoffset = 0;
8320 rsurface.batchtvector3f = NULL;
8321 rsurface.batchtvector3f_vertexbuffer = NULL;
8322 rsurface.batchtvector3f_bufferoffset = 0;
8323 rsurface.batchnormal3f = NULL;
8324 rsurface.batchnormal3f_vertexbuffer = NULL;
8325 rsurface.batchnormal3f_bufferoffset = 0;
8326 rsurface.batchlightmapcolor4f = NULL;
8327 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8328 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8329 rsurface.batchtexcoordtexture2f = NULL;
8330 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8331 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8332 rsurface.batchtexcoordlightmap2f = NULL;
8333 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8334 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8335 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8336 rsurface.batchelement3i_indexbuffer = NULL;
8337 rsurface.batchelement3i_bufferoffset = 0;
8338 rsurface.batchelement3s = NULL;
8339 rsurface.batchelement3s_indexbuffer = NULL;
8340 rsurface.batchelement3s_bufferoffset = 0;
8341 // we'll only be setting up certain arrays as needed
8342 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8343 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8344 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8345 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8346 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8347 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8348 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8350 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8351 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8353 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8354 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8355 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8356 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8357 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8358 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8361 for (i = 0;i < texturenumsurfaces;i++)
8363 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8364 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8365 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8366 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8367 // copy only the data requested
8368 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8369 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8370 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8372 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8373 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8374 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8375 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8376 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8378 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8379 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8381 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8382 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8383 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8384 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8385 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8386 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8388 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8389 numvertices += surfacenumvertices;
8390 numtriangles += surfacenumtriangles;
8393 // generate a 16bit index array as well if possible
8394 // (in general, dynamic batches fit)
8395 if (numvertices <= 65536)
8397 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8398 for (i = 0;i < numtriangles*3;i++)
8399 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8402 // since we've copied everything, the batch now starts at 0
8403 rsurface.batchfirstvertex = 0;
8404 rsurface.batchnumvertices = batchnumvertices;
8405 rsurface.batchfirsttriangle = 0;
8406 rsurface.batchnumtriangles = batchnumtriangles;
8409 // q1bsp surfaces rendered in vertex color mode have to have colors
8410 // calculated based on lightstyles
8411 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8413 // generate color arrays for the surfaces in this list
8418 const unsigned char *lm;
8419 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8420 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8421 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8423 for (i = 0;i < texturenumsurfaces;i++)
8425 surface = texturesurfacelist[i];
8426 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8427 surfacenumvertices = surface->num_vertices;
8428 if (surface->lightmapinfo->samples)
8430 for (j = 0;j < surfacenumvertices;j++)
8432 lm = surface->lightmapinfo->samples + offsets[j];
8433 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8434 VectorScale(lm, scale, c);
8435 if (surface->lightmapinfo->styles[1] != 255)
8437 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8439 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8440 VectorMA(c, scale, lm, c);
8441 if (surface->lightmapinfo->styles[2] != 255)
8444 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8445 VectorMA(c, scale, lm, c);
8446 if (surface->lightmapinfo->styles[3] != 255)
8449 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8450 VectorMA(c, scale, lm, c);
8457 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);
8463 for (j = 0;j < surfacenumvertices;j++)
8465 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8472 // if vertices are deformed (sprite flares and things in maps, possibly
8473 // water waves, bulges and other deformations), modify the copied vertices
8475 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8477 switch (deform->deform)
8480 case Q3DEFORM_PROJECTIONSHADOW:
8481 case Q3DEFORM_TEXT0:
8482 case Q3DEFORM_TEXT1:
8483 case Q3DEFORM_TEXT2:
8484 case Q3DEFORM_TEXT3:
8485 case Q3DEFORM_TEXT4:
8486 case Q3DEFORM_TEXT5:
8487 case Q3DEFORM_TEXT6:
8488 case Q3DEFORM_TEXT7:
8491 case Q3DEFORM_AUTOSPRITE:
8492 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8493 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8494 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8495 VectorNormalize(newforward);
8496 VectorNormalize(newright);
8497 VectorNormalize(newup);
8498 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8499 // rsurface.batchvertex3f_vertexbuffer = NULL;
8500 // rsurface.batchvertex3f_bufferoffset = 0;
8501 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8502 // rsurface.batchsvector3f_vertexbuffer = NULL;
8503 // rsurface.batchsvector3f_bufferoffset = 0;
8504 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8505 // rsurface.batchtvector3f_vertexbuffer = NULL;
8506 // rsurface.batchtvector3f_bufferoffset = 0;
8507 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8508 // rsurface.batchnormal3f_vertexbuffer = NULL;
8509 // rsurface.batchnormal3f_bufferoffset = 0;
8510 // a single autosprite surface can contain multiple sprites...
8511 for (j = 0;j < batchnumvertices - 3;j += 4)
8513 VectorClear(center);
8514 for (i = 0;i < 4;i++)
8515 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8516 VectorScale(center, 0.25f, center);
8517 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8518 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8519 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8520 for (i = 0;i < 4;i++)
8522 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8523 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8526 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8527 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8528 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);
8530 case Q3DEFORM_AUTOSPRITE2:
8531 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8532 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8533 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8534 VectorNormalize(newforward);
8535 VectorNormalize(newright);
8536 VectorNormalize(newup);
8537 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8538 // rsurface.batchvertex3f_vertexbuffer = NULL;
8539 // rsurface.batchvertex3f_bufferoffset = 0;
8541 const float *v1, *v2;
8551 memset(shortest, 0, sizeof(shortest));
8552 // a single autosprite surface can contain multiple sprites...
8553 for (j = 0;j < batchnumvertices - 3;j += 4)
8555 VectorClear(center);
8556 for (i = 0;i < 4;i++)
8557 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8558 VectorScale(center, 0.25f, center);
8559 // find the two shortest edges, then use them to define the
8560 // axis vectors for rotating around the central axis
8561 for (i = 0;i < 6;i++)
8563 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8564 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8565 l = VectorDistance2(v1, v2);
8566 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8568 l += (1.0f / 1024.0f);
8569 if (shortest[0].length2 > l || i == 0)
8571 shortest[1] = shortest[0];
8572 shortest[0].length2 = l;
8573 shortest[0].v1 = v1;
8574 shortest[0].v2 = v2;
8576 else if (shortest[1].length2 > l || i == 1)
8578 shortest[1].length2 = l;
8579 shortest[1].v1 = v1;
8580 shortest[1].v2 = v2;
8583 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8584 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8585 // this calculates the right vector from the shortest edge
8586 // and the up vector from the edge midpoints
8587 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8588 VectorNormalize(right);
8589 VectorSubtract(end, start, up);
8590 VectorNormalize(up);
8591 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8592 VectorSubtract(rsurface.localvieworigin, center, forward);
8593 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8594 VectorNegate(forward, forward);
8595 VectorReflect(forward, 0, up, forward);
8596 VectorNormalize(forward);
8597 CrossProduct(up, forward, newright);
8598 VectorNormalize(newright);
8599 // rotate the quad around the up axis vector, this is made
8600 // especially easy by the fact we know the quad is flat,
8601 // so we only have to subtract the center position and
8602 // measure distance along the right vector, and then
8603 // multiply that by the newright vector and add back the
8605 // we also need to subtract the old position to undo the
8606 // displacement from the center, which we do with a
8607 // DotProduct, the subtraction/addition of center is also
8608 // optimized into DotProducts here
8609 l = DotProduct(right, center);
8610 for (i = 0;i < 4;i++)
8612 v1 = rsurface.batchvertex3f + 3*(j+i);
8613 f = DotProduct(right, v1) - l;
8614 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8618 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8620 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8621 // rsurface.batchnormal3f_vertexbuffer = NULL;
8622 // rsurface.batchnormal3f_bufferoffset = 0;
8623 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8625 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8627 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8628 // rsurface.batchsvector3f_vertexbuffer = NULL;
8629 // rsurface.batchsvector3f_bufferoffset = 0;
8630 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8631 // rsurface.batchtvector3f_vertexbuffer = NULL;
8632 // rsurface.batchtvector3f_bufferoffset = 0;
8633 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);
8636 case Q3DEFORM_NORMAL:
8637 // deform the normals to make reflections wavey
8638 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8639 rsurface.batchnormal3f_vertexbuffer = NULL;
8640 rsurface.batchnormal3f_bufferoffset = 0;
8641 for (j = 0;j < batchnumvertices;j++)
8644 float *normal = rsurface.batchnormal3f + 3*j;
8645 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8646 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8647 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]);
8648 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]);
8649 VectorNormalize(normal);
8651 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8653 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8654 // rsurface.batchsvector3f_vertexbuffer = NULL;
8655 // rsurface.batchsvector3f_bufferoffset = 0;
8656 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8657 // rsurface.batchtvector3f_vertexbuffer = NULL;
8658 // rsurface.batchtvector3f_bufferoffset = 0;
8659 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);
8663 // deform vertex array to make wavey water and flags and such
8664 waveparms[0] = deform->waveparms[0];
8665 waveparms[1] = deform->waveparms[1];
8666 waveparms[2] = deform->waveparms[2];
8667 waveparms[3] = deform->waveparms[3];
8668 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8669 break; // if wavefunc is a nop, don't make a dynamic vertex array
8670 // this is how a divisor of vertex influence on deformation
8671 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8672 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8673 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8674 // rsurface.batchvertex3f_vertexbuffer = NULL;
8675 // rsurface.batchvertex3f_bufferoffset = 0;
8676 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8677 // rsurface.batchnormal3f_vertexbuffer = NULL;
8678 // rsurface.batchnormal3f_bufferoffset = 0;
8679 for (j = 0;j < batchnumvertices;j++)
8681 // if the wavefunc depends on time, evaluate it per-vertex
8684 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8685 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8687 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8689 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8690 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8691 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8693 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8694 // rsurface.batchsvector3f_vertexbuffer = NULL;
8695 // rsurface.batchsvector3f_bufferoffset = 0;
8696 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8697 // rsurface.batchtvector3f_vertexbuffer = NULL;
8698 // rsurface.batchtvector3f_bufferoffset = 0;
8699 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);
8702 case Q3DEFORM_BULGE:
8703 // deform vertex array to make the surface have moving bulges
8704 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8705 // rsurface.batchvertex3f_vertexbuffer = NULL;
8706 // rsurface.batchvertex3f_bufferoffset = 0;
8707 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8708 // rsurface.batchnormal3f_vertexbuffer = NULL;
8709 // rsurface.batchnormal3f_bufferoffset = 0;
8710 for (j = 0;j < batchnumvertices;j++)
8712 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8713 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8715 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8716 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8717 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8719 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8720 // rsurface.batchsvector3f_vertexbuffer = NULL;
8721 // rsurface.batchsvector3f_bufferoffset = 0;
8722 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8723 // rsurface.batchtvector3f_vertexbuffer = NULL;
8724 // rsurface.batchtvector3f_bufferoffset = 0;
8725 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);
8729 // deform vertex array
8730 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8731 break; // if wavefunc is a nop, don't make a dynamic vertex array
8732 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8733 VectorScale(deform->parms, scale, waveparms);
8734 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8735 // rsurface.batchvertex3f_vertexbuffer = NULL;
8736 // rsurface.batchvertex3f_bufferoffset = 0;
8737 for (j = 0;j < batchnumvertices;j++)
8738 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8743 // generate texcoords based on the chosen texcoord source
8744 switch(rsurface.texture->tcgen.tcgen)
8747 case Q3TCGEN_TEXTURE:
8749 case Q3TCGEN_LIGHTMAP:
8750 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8751 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8752 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8753 if (rsurface.batchtexcoordlightmap2f)
8754 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8756 case Q3TCGEN_VECTOR:
8757 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8758 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8759 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8760 for (j = 0;j < batchnumvertices;j++)
8762 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8763 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8766 case Q3TCGEN_ENVIRONMENT:
8767 // make environment reflections using a spheremap
8768 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8769 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8770 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8771 for (j = 0;j < batchnumvertices;j++)
8773 // identical to Q3A's method, but executed in worldspace so
8774 // carried models can be shiny too
8776 float viewer[3], d, reflected[3], worldreflected[3];
8778 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8779 // VectorNormalize(viewer);
8781 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8783 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8784 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8785 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8786 // note: this is proportinal to viewer, so we can normalize later
8788 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8789 VectorNormalize(worldreflected);
8791 // note: this sphere map only uses world x and z!
8792 // so positive and negative y will LOOK THE SAME.
8793 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8794 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8798 // the only tcmod that needs software vertex processing is turbulent, so
8799 // check for it here and apply the changes if needed
8800 // and we only support that as the first one
8801 // (handling a mixture of turbulent and other tcmods would be problematic
8802 // without punting it entirely to a software path)
8803 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8805 amplitude = rsurface.texture->tcmods[0].parms[1];
8806 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8807 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8808 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8809 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8810 for (j = 0;j < batchnumvertices;j++)
8812 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);
8813 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8817 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8819 // convert the modified arrays to vertex structs
8820 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8821 // rsurface.batchvertexmeshbuffer = NULL;
8822 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8823 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8824 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8825 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8826 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8827 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8828 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8830 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8832 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8833 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8836 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8837 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8838 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8839 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8840 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8841 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8842 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8843 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8844 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8848 void RSurf_DrawBatch(void)
8850 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8851 // through the pipeline, killing it earlier in the pipeline would have
8852 // per-surface overhead rather than per-batch overhead, so it's best to
8853 // reject it here, before it hits glDraw.
8854 if (rsurface.batchnumtriangles == 0)
8857 // batch debugging code
8858 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8864 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8865 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8868 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8870 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8872 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8873 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);
8880 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);
8883 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8885 // pick the closest matching water plane
8886 int planeindex, vertexindex, bestplaneindex = -1;
8890 r_waterstate_waterplane_t *p;
8891 qboolean prepared = false;
8893 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8895 if(p->camera_entity != rsurface.texture->camera_entity)
8900 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8902 if(rsurface.batchnumvertices == 0)
8905 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8907 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8908 d += fabs(PlaneDiff(vert, &p->plane));
8910 if (bestd > d || bestplaneindex < 0)
8913 bestplaneindex = planeindex;
8916 return bestplaneindex;
8917 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8918 // this situation though, as it might be better to render single larger
8919 // batches with useless stuff (backface culled for example) than to
8920 // render multiple smaller batches
8923 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8926 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8927 rsurface.passcolor4f_vertexbuffer = 0;
8928 rsurface.passcolor4f_bufferoffset = 0;
8929 for (i = 0;i < rsurface.batchnumvertices;i++)
8930 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8933 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8940 if (rsurface.passcolor4f)
8942 // generate color arrays
8943 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8944 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8945 rsurface.passcolor4f_vertexbuffer = 0;
8946 rsurface.passcolor4f_bufferoffset = 0;
8947 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)
8949 f = RSurf_FogVertex(v);
8958 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8959 rsurface.passcolor4f_vertexbuffer = 0;
8960 rsurface.passcolor4f_bufferoffset = 0;
8961 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8963 f = RSurf_FogVertex(v);
8972 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8979 if (!rsurface.passcolor4f)
8981 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8982 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8983 rsurface.passcolor4f_vertexbuffer = 0;
8984 rsurface.passcolor4f_bufferoffset = 0;
8985 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)
8987 f = RSurf_FogVertex(v);
8988 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8989 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8990 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8995 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9000 if (!rsurface.passcolor4f)
9002 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9003 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9004 rsurface.passcolor4f_vertexbuffer = 0;
9005 rsurface.passcolor4f_bufferoffset = 0;
9006 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9015 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9020 if (!rsurface.passcolor4f)
9022 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9023 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9024 rsurface.passcolor4f_vertexbuffer = 0;
9025 rsurface.passcolor4f_bufferoffset = 0;
9026 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9028 c2[0] = c[0] + r_refdef.scene.ambient;
9029 c2[1] = c[1] + r_refdef.scene.ambient;
9030 c2[2] = c[2] + r_refdef.scene.ambient;
9035 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9038 rsurface.passcolor4f = NULL;
9039 rsurface.passcolor4f_vertexbuffer = 0;
9040 rsurface.passcolor4f_bufferoffset = 0;
9041 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9042 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9043 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9044 GL_Color(r, g, b, a);
9045 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9049 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9051 // TODO: optimize applyfog && applycolor case
9052 // just apply fog if necessary, and tint the fog color array if necessary
9053 rsurface.passcolor4f = NULL;
9054 rsurface.passcolor4f_vertexbuffer = 0;
9055 rsurface.passcolor4f_bufferoffset = 0;
9056 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9057 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9058 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9059 GL_Color(r, g, b, a);
9063 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9066 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9067 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9068 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9069 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9070 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9071 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9072 GL_Color(r, g, b, a);
9076 static void RSurf_DrawBatch_GL11_ClampColor(void)
9081 if (!rsurface.passcolor4f)
9083 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9085 c2[0] = bound(0.0f, c1[0], 1.0f);
9086 c2[1] = bound(0.0f, c1[1], 1.0f);
9087 c2[2] = bound(0.0f, c1[2], 1.0f);
9088 c2[3] = bound(0.0f, c1[3], 1.0f);
9092 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9102 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9103 rsurface.passcolor4f_vertexbuffer = 0;
9104 rsurface.passcolor4f_bufferoffset = 0;
9105 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)
9107 f = -DotProduct(r_refdef.view.forward, n);
9109 f = f * 0.85 + 0.15; // work around so stuff won't get black
9110 f *= r_refdef.lightmapintensity;
9111 Vector4Set(c, f, f, f, 1);
9115 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9117 RSurf_DrawBatch_GL11_ApplyFakeLight();
9118 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9119 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9120 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9121 GL_Color(r, g, b, a);
9125 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9133 vec3_t ambientcolor;
9134 vec3_t diffusecolor;
9138 VectorCopy(rsurface.modellight_lightdir, lightdir);
9139 f = 0.5f * r_refdef.lightmapintensity;
9140 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9141 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9142 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9143 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9144 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9145 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9147 if (VectorLength2(diffusecolor) > 0)
9149 // q3-style directional shading
9150 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9151 rsurface.passcolor4f_vertexbuffer = 0;
9152 rsurface.passcolor4f_bufferoffset = 0;
9153 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)
9155 if ((f = DotProduct(n, lightdir)) > 0)
9156 VectorMA(ambientcolor, f, diffusecolor, c);
9158 VectorCopy(ambientcolor, c);
9165 *applycolor = false;
9169 *r = ambientcolor[0];
9170 *g = ambientcolor[1];
9171 *b = ambientcolor[2];
9172 rsurface.passcolor4f = NULL;
9173 rsurface.passcolor4f_vertexbuffer = 0;
9174 rsurface.passcolor4f_bufferoffset = 0;
9178 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9180 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9181 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9182 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9183 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9184 GL_Color(r, g, b, a);
9188 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9194 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9196 f = 1 - RSurf_FogVertex(v);
9204 void RSurf_SetupDepthAndCulling(void)
9206 // submodels are biased to avoid z-fighting with world surfaces that they
9207 // may be exactly overlapping (avoids z-fighting artifacts on certain
9208 // doors and things in Quake maps)
9209 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9210 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9211 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9212 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9215 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9217 // transparent sky would be ridiculous
9218 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9220 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9221 skyrenderlater = true;
9222 RSurf_SetupDepthAndCulling();
9224 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9225 // skymasking on them, and Quake3 never did sky masking (unlike
9226 // software Quake and software Quake2), so disable the sky masking
9227 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9228 // and skymasking also looks very bad when noclipping outside the
9229 // level, so don't use it then either.
9230 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9232 R_Mesh_ResetTextureState();
9233 if (skyrendermasked)
9235 R_SetupShader_DepthOrShadow();
9236 // depth-only (masking)
9237 GL_ColorMask(0,0,0,0);
9238 // just to make sure that braindead drivers don't draw
9239 // anything despite that colormask...
9240 GL_BlendFunc(GL_ZERO, GL_ONE);
9241 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9242 if (rsurface.batchvertex3fbuffer)
9243 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9245 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9249 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9251 GL_BlendFunc(GL_ONE, GL_ZERO);
9252 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9253 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9254 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9257 if (skyrendermasked)
9258 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9260 R_Mesh_ResetTextureState();
9261 GL_Color(1, 1, 1, 1);
9264 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9265 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9266 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9268 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9272 // render screenspace normalmap to texture
9274 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9279 // bind lightmap texture
9281 // water/refraction/reflection/camera surfaces have to be handled specially
9282 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9284 int start, end, startplaneindex;
9285 for (start = 0;start < texturenumsurfaces;start = end)
9287 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9288 if(startplaneindex < 0)
9290 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9291 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9295 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9297 // now that we have a batch using the same planeindex, render it
9298 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9300 // render water or distortion background
9302 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));
9304 // blend surface on top
9305 GL_DepthMask(false);
9306 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9309 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9311 // render surface with reflection texture as input
9312 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9313 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));
9320 // render surface batch normally
9321 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9322 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9326 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9328 // OpenGL 1.3 path - anything not completely ancient
9329 qboolean applycolor;
9332 const texturelayer_t *layer;
9333 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);
9334 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9336 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9339 int layertexrgbscale;
9340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9342 if (layerindex == 0)
9346 GL_AlphaTest(false);
9347 GL_DepthFunc(GL_EQUAL);
9350 GL_DepthMask(layer->depthmask && writedepth);
9351 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9352 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9354 layertexrgbscale = 4;
9355 VectorScale(layer->color, 0.25f, layercolor);
9357 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9359 layertexrgbscale = 2;
9360 VectorScale(layer->color, 0.5f, layercolor);
9364 layertexrgbscale = 1;
9365 VectorScale(layer->color, 1.0f, layercolor);
9367 layercolor[3] = layer->color[3];
9368 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9369 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9370 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9371 switch (layer->type)
9373 case TEXTURELAYERTYPE_LITTEXTURE:
9374 // single-pass lightmapped texture with 2x rgbscale
9375 R_Mesh_TexBind(0, r_texture_white);
9376 R_Mesh_TexMatrix(0, NULL);
9377 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9378 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9379 R_Mesh_TexBind(1, layer->texture);
9380 R_Mesh_TexMatrix(1, &layer->texmatrix);
9381 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9382 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9383 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9384 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9385 else if (FAKELIGHT_ENABLED)
9386 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9387 else if (rsurface.uselightmaptexture)
9388 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9390 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9392 case TEXTURELAYERTYPE_TEXTURE:
9393 // singletexture unlit texture with transparency support
9394 R_Mesh_TexBind(0, layer->texture);
9395 R_Mesh_TexMatrix(0, &layer->texmatrix);
9396 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9397 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9398 R_Mesh_TexBind(1, 0);
9399 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9400 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9402 case TEXTURELAYERTYPE_FOG:
9403 // singletexture fogging
9406 R_Mesh_TexBind(0, layer->texture);
9407 R_Mesh_TexMatrix(0, &layer->texmatrix);
9408 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9409 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9413 R_Mesh_TexBind(0, 0);
9414 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9416 R_Mesh_TexBind(1, 0);
9417 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9418 // generate a color array for the fog pass
9419 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9420 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9424 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9427 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9429 GL_DepthFunc(GL_LEQUAL);
9430 GL_AlphaTest(false);
9434 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9436 // OpenGL 1.1 - crusty old voodoo path
9439 const texturelayer_t *layer;
9440 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);
9441 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9443 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9445 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9447 if (layerindex == 0)
9451 GL_AlphaTest(false);
9452 GL_DepthFunc(GL_EQUAL);
9455 GL_DepthMask(layer->depthmask && writedepth);
9456 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9457 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9458 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9459 switch (layer->type)
9461 case TEXTURELAYERTYPE_LITTEXTURE:
9462 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9464 // two-pass lit texture with 2x rgbscale
9465 // first the lightmap pass
9466 R_Mesh_TexBind(0, r_texture_white);
9467 R_Mesh_TexMatrix(0, NULL);
9468 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9469 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9470 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9471 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9472 else if (FAKELIGHT_ENABLED)
9473 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9474 else if (rsurface.uselightmaptexture)
9475 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9477 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9478 // then apply the texture to it
9479 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9480 R_Mesh_TexBind(0, layer->texture);
9481 R_Mesh_TexMatrix(0, &layer->texmatrix);
9482 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9483 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9484 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);
9488 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9489 R_Mesh_TexBind(0, layer->texture);
9490 R_Mesh_TexMatrix(0, &layer->texmatrix);
9491 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9492 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9493 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9494 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);
9496 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);
9499 case TEXTURELAYERTYPE_TEXTURE:
9500 // singletexture unlit texture with transparency support
9501 R_Mesh_TexBind(0, layer->texture);
9502 R_Mesh_TexMatrix(0, &layer->texmatrix);
9503 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9504 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9505 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);
9507 case TEXTURELAYERTYPE_FOG:
9508 // singletexture fogging
9511 R_Mesh_TexBind(0, layer->texture);
9512 R_Mesh_TexMatrix(0, &layer->texmatrix);
9513 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9514 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9518 R_Mesh_TexBind(0, 0);
9519 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9521 // generate a color array for the fog pass
9522 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9523 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9527 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9530 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9532 GL_DepthFunc(GL_LEQUAL);
9533 GL_AlphaTest(false);
9537 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9541 r_vertexgeneric_t *batchvertex;
9544 // R_Mesh_ResetTextureState();
9545 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9547 if(rsurface.texture && rsurface.texture->currentskinframe)
9549 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9550 c[3] *= rsurface.texture->currentalpha;
9560 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9562 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9563 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9564 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9567 // brighten it up (as texture value 127 means "unlit")
9568 c[0] *= 2 * r_refdef.view.colorscale;
9569 c[1] *= 2 * r_refdef.view.colorscale;
9570 c[2] *= 2 * r_refdef.view.colorscale;
9572 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9573 c[3] *= r_wateralpha.value;
9575 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9577 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9578 GL_DepthMask(false);
9580 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9582 GL_BlendFunc(GL_ONE, GL_ONE);
9583 GL_DepthMask(false);
9585 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9587 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9588 GL_DepthMask(false);
9590 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9592 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9593 GL_DepthMask(false);
9597 GL_BlendFunc(GL_ONE, GL_ZERO);
9598 GL_DepthMask(writedepth);
9601 if (r_showsurfaces.integer == 3)
9603 rsurface.passcolor4f = NULL;
9605 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9607 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9609 rsurface.passcolor4f = NULL;
9610 rsurface.passcolor4f_vertexbuffer = 0;
9611 rsurface.passcolor4f_bufferoffset = 0;
9613 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9615 qboolean applycolor = true;
9618 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9620 r_refdef.lightmapintensity = 1;
9621 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9622 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9624 else if (FAKELIGHT_ENABLED)
9626 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9628 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9629 RSurf_DrawBatch_GL11_ApplyFakeLight();
9630 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9634 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9636 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9637 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9638 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9641 if(!rsurface.passcolor4f)
9642 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9644 RSurf_DrawBatch_GL11_ApplyAmbient();
9645 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9646 if(r_refdef.fogenabled)
9647 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9648 RSurf_DrawBatch_GL11_ClampColor();
9650 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9651 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9654 else if (!r_refdef.view.showdebug)
9656 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9657 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9658 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9660 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9661 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9663 R_Mesh_PrepareVertices_Generic_Unlock();
9666 else if (r_showsurfaces.integer == 4)
9668 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9669 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9670 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9672 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9673 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9674 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9676 R_Mesh_PrepareVertices_Generic_Unlock();
9679 else if (r_showsurfaces.integer == 2)
9682 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9683 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9684 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9686 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9687 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9688 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9689 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9690 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9691 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9692 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9694 R_Mesh_PrepareVertices_Generic_Unlock();
9695 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9699 int texturesurfaceindex;
9701 const msurface_t *surface;
9702 float surfacecolor4f[4];
9703 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9704 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9706 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9708 surface = texturesurfacelist[texturesurfaceindex];
9709 k = (int)(((size_t)surface) / sizeof(msurface_t));
9710 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9711 for (j = 0;j < surface->num_vertices;j++)
9713 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9714 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9718 R_Mesh_PrepareVertices_Generic_Unlock();
9723 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9726 RSurf_SetupDepthAndCulling();
9727 if (r_showsurfaces.integer)
9729 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9732 switch (vid.renderpath)
9734 case RENDERPATH_GL20:
9735 case RENDERPATH_D3D9:
9736 case RENDERPATH_D3D10:
9737 case RENDERPATH_D3D11:
9738 case RENDERPATH_SOFT:
9739 case RENDERPATH_GLES2:
9740 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9742 case RENDERPATH_GL13:
9743 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9745 case RENDERPATH_GL11:
9746 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9752 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9755 RSurf_SetupDepthAndCulling();
9756 if (r_showsurfaces.integer)
9758 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9761 switch (vid.renderpath)
9763 case RENDERPATH_GL20:
9764 case RENDERPATH_D3D9:
9765 case RENDERPATH_D3D10:
9766 case RENDERPATH_D3D11:
9767 case RENDERPATH_SOFT:
9768 case RENDERPATH_GLES2:
9769 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9771 case RENDERPATH_GL13:
9772 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9774 case RENDERPATH_GL11:
9775 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9781 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9784 int texturenumsurfaces, endsurface;
9786 const msurface_t *surface;
9787 #define MAXBATCH_TRANSPARENTSURFACES 256
9788 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9790 // if the model is static it doesn't matter what value we give for
9791 // wantnormals and wanttangents, so this logic uses only rules applicable
9792 // to a model, knowing that they are meaningless otherwise
9793 if (ent == r_refdef.scene.worldentity)
9794 RSurf_ActiveWorldEntity();
9795 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9796 RSurf_ActiveModelEntity(ent, false, false, false);
9799 switch (vid.renderpath)
9801 case RENDERPATH_GL20:
9802 case RENDERPATH_D3D9:
9803 case RENDERPATH_D3D10:
9804 case RENDERPATH_D3D11:
9805 case RENDERPATH_SOFT:
9806 case RENDERPATH_GLES2:
9807 RSurf_ActiveModelEntity(ent, true, true, false);
9809 case RENDERPATH_GL13:
9810 case RENDERPATH_GL11:
9811 RSurf_ActiveModelEntity(ent, true, false, false);
9816 if (r_transparentdepthmasking.integer)
9818 qboolean setup = false;
9819 for (i = 0;i < numsurfaces;i = j)
9822 surface = rsurface.modelsurfaces + surfacelist[i];
9823 texture = surface->texture;
9824 rsurface.texture = R_GetCurrentTexture(texture);
9825 rsurface.lightmaptexture = NULL;
9826 rsurface.deluxemaptexture = NULL;
9827 rsurface.uselightmaptexture = false;
9828 // scan ahead until we find a different texture
9829 endsurface = min(i + 1024, numsurfaces);
9830 texturenumsurfaces = 0;
9831 texturesurfacelist[texturenumsurfaces++] = surface;
9832 for (;j < endsurface;j++)
9834 surface = rsurface.modelsurfaces + surfacelist[j];
9835 if (texture != surface->texture)
9837 texturesurfacelist[texturenumsurfaces++] = surface;
9839 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9841 // render the range of surfaces as depth
9845 GL_ColorMask(0,0,0,0);
9848 GL_BlendFunc(GL_ONE, GL_ZERO);
9850 // R_Mesh_ResetTextureState();
9851 R_SetupShader_DepthOrShadow();
9853 RSurf_SetupDepthAndCulling();
9854 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9855 if (rsurface.batchvertex3fbuffer)
9856 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9858 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9862 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9865 for (i = 0;i < numsurfaces;i = j)
9868 surface = rsurface.modelsurfaces + surfacelist[i];
9869 texture = surface->texture;
9870 rsurface.texture = R_GetCurrentTexture(texture);
9871 // scan ahead until we find a different texture
9872 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9873 texturenumsurfaces = 0;
9874 texturesurfacelist[texturenumsurfaces++] = surface;
9875 if(FAKELIGHT_ENABLED)
9877 rsurface.lightmaptexture = NULL;
9878 rsurface.deluxemaptexture = NULL;
9879 rsurface.uselightmaptexture = false;
9880 for (;j < endsurface;j++)
9882 surface = rsurface.modelsurfaces + surfacelist[j];
9883 if (texture != surface->texture)
9885 texturesurfacelist[texturenumsurfaces++] = surface;
9890 rsurface.lightmaptexture = surface->lightmaptexture;
9891 rsurface.deluxemaptexture = surface->deluxemaptexture;
9892 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9893 for (;j < endsurface;j++)
9895 surface = rsurface.modelsurfaces + surfacelist[j];
9896 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9898 texturesurfacelist[texturenumsurfaces++] = surface;
9901 // render the range of surfaces
9902 if (ent == r_refdef.scene.worldentity)
9903 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9905 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9907 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9910 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9912 // transparent surfaces get pushed off into the transparent queue
9913 int surfacelistindex;
9914 const msurface_t *surface;
9915 vec3_t tempcenter, center;
9916 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9918 surface = texturesurfacelist[surfacelistindex];
9919 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9920 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9921 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9922 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9923 if (queueentity->transparent_offset) // transparent offset
9925 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9926 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9927 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9929 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9933 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9935 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9937 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9939 RSurf_SetupDepthAndCulling();
9940 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9941 if (rsurface.batchvertex3fbuffer)
9942 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9944 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9948 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9950 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9953 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9956 if (!rsurface.texture->currentnumlayers)
9958 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9959 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9961 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9963 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9964 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9965 else if (!rsurface.texture->currentnumlayers)
9967 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9969 // in the deferred case, transparent surfaces were queued during prepass
9970 if (!r_shadow_usingdeferredprepass)
9971 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9975 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9976 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9981 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9985 R_FrameData_SetMark();
9986 // break the surface list down into batches by texture and use of lightmapping
9987 for (i = 0;i < numsurfaces;i = j)
9990 // texture is the base texture pointer, rsurface.texture is the
9991 // current frame/skin the texture is directing us to use (for example
9992 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9993 // use skin 1 instead)
9994 texture = surfacelist[i]->texture;
9995 rsurface.texture = R_GetCurrentTexture(texture);
9996 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9998 // if this texture is not the kind we want, skip ahead to the next one
9999 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10003 if(FAKELIGHT_ENABLED || depthonly || prepass)
10005 rsurface.lightmaptexture = NULL;
10006 rsurface.deluxemaptexture = NULL;
10007 rsurface.uselightmaptexture = false;
10008 // simply scan ahead until we find a different texture or lightmap state
10009 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10014 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10015 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10016 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10017 // simply scan ahead until we find a different texture or lightmap state
10018 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10021 // render the range of surfaces
10022 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10024 R_FrameData_ReturnToMark();
10027 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10031 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10034 if (!rsurface.texture->currentnumlayers)
10036 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10037 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10039 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10041 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10042 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10043 else if (!rsurface.texture->currentnumlayers)
10045 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10047 // in the deferred case, transparent surfaces were queued during prepass
10048 if (!r_shadow_usingdeferredprepass)
10049 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10053 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10054 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10059 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10062 texture_t *texture;
10063 R_FrameData_SetMark();
10064 // break the surface list down into batches by texture and use of lightmapping
10065 for (i = 0;i < numsurfaces;i = j)
10068 // texture is the base texture pointer, rsurface.texture is the
10069 // current frame/skin the texture is directing us to use (for example
10070 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10071 // use skin 1 instead)
10072 texture = surfacelist[i]->texture;
10073 rsurface.texture = R_GetCurrentTexture(texture);
10074 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10076 // if this texture is not the kind we want, skip ahead to the next one
10077 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10081 if(FAKELIGHT_ENABLED || depthonly || prepass)
10083 rsurface.lightmaptexture = NULL;
10084 rsurface.deluxemaptexture = NULL;
10085 rsurface.uselightmaptexture = false;
10086 // simply scan ahead until we find a different texture or lightmap state
10087 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10092 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10093 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10094 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10095 // simply scan ahead until we find a different texture or lightmap state
10096 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10099 // render the range of surfaces
10100 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10102 R_FrameData_ReturnToMark();
10105 float locboxvertex3f[6*4*3] =
10107 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10108 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10109 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10110 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10111 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10112 1,0,0, 0,0,0, 0,1,0, 1,1,0
10115 unsigned short locboxelements[6*2*3] =
10120 12,13,14, 12,14,15,
10121 16,17,18, 16,18,19,
10125 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10128 cl_locnode_t *loc = (cl_locnode_t *)ent;
10130 float vertex3f[6*4*3];
10132 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10133 GL_DepthMask(false);
10134 GL_DepthRange(0, 1);
10135 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10136 GL_DepthTest(true);
10137 GL_CullFace(GL_NONE);
10138 R_EntityMatrix(&identitymatrix);
10140 // R_Mesh_ResetTextureState();
10142 i = surfacelist[0];
10143 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10144 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10145 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10146 surfacelist[0] < 0 ? 0.5f : 0.125f);
10148 if (VectorCompare(loc->mins, loc->maxs))
10150 VectorSet(size, 2, 2, 2);
10151 VectorMA(loc->mins, -0.5f, size, mins);
10155 VectorCopy(loc->mins, mins);
10156 VectorSubtract(loc->maxs, loc->mins, size);
10159 for (i = 0;i < 6*4*3;)
10160 for (j = 0;j < 3;j++, i++)
10161 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10163 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10164 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10165 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10168 void R_DrawLocs(void)
10171 cl_locnode_t *loc, *nearestloc;
10173 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10174 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10176 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10177 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10181 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10183 if (decalsystem->decals)
10184 Mem_Free(decalsystem->decals);
10185 memset(decalsystem, 0, sizeof(*decalsystem));
10188 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)
10191 tridecal_t *decals;
10194 // expand or initialize the system
10195 if (decalsystem->maxdecals <= decalsystem->numdecals)
10197 decalsystem_t old = *decalsystem;
10198 qboolean useshortelements;
10199 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10200 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10201 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)));
10202 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10203 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10204 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10205 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10206 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10207 if (decalsystem->numdecals)
10208 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10210 Mem_Free(old.decals);
10211 for (i = 0;i < decalsystem->maxdecals*3;i++)
10212 decalsystem->element3i[i] = i;
10213 if (useshortelements)
10214 for (i = 0;i < decalsystem->maxdecals*3;i++)
10215 decalsystem->element3s[i] = i;
10218 // grab a decal and search for another free slot for the next one
10219 decals = decalsystem->decals;
10220 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10221 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10223 decalsystem->freedecal = i;
10224 if (decalsystem->numdecals <= i)
10225 decalsystem->numdecals = i + 1;
10227 // initialize the decal
10229 decal->triangleindex = triangleindex;
10230 decal->surfaceindex = surfaceindex;
10231 decal->decalsequence = decalsequence;
10232 decal->color4f[0][0] = c0[0];
10233 decal->color4f[0][1] = c0[1];
10234 decal->color4f[0][2] = c0[2];
10235 decal->color4f[0][3] = 1;
10236 decal->color4f[1][0] = c1[0];
10237 decal->color4f[1][1] = c1[1];
10238 decal->color4f[1][2] = c1[2];
10239 decal->color4f[1][3] = 1;
10240 decal->color4f[2][0] = c2[0];
10241 decal->color4f[2][1] = c2[1];
10242 decal->color4f[2][2] = c2[2];
10243 decal->color4f[2][3] = 1;
10244 decal->vertex3f[0][0] = v0[0];
10245 decal->vertex3f[0][1] = v0[1];
10246 decal->vertex3f[0][2] = v0[2];
10247 decal->vertex3f[1][0] = v1[0];
10248 decal->vertex3f[1][1] = v1[1];
10249 decal->vertex3f[1][2] = v1[2];
10250 decal->vertex3f[2][0] = v2[0];
10251 decal->vertex3f[2][1] = v2[1];
10252 decal->vertex3f[2][2] = v2[2];
10253 decal->texcoord2f[0][0] = t0[0];
10254 decal->texcoord2f[0][1] = t0[1];
10255 decal->texcoord2f[1][0] = t1[0];
10256 decal->texcoord2f[1][1] = t1[1];
10257 decal->texcoord2f[2][0] = t2[0];
10258 decal->texcoord2f[2][1] = t2[1];
10261 extern cvar_t cl_decals_bias;
10262 extern cvar_t cl_decals_models;
10263 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10264 // baseparms, parms, temps
10265 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)
10270 const float *vertex3f;
10271 const float *normal3f;
10273 float points[2][9][3];
10280 e = rsurface.modelelement3i + 3*triangleindex;
10282 vertex3f = rsurface.modelvertex3f;
10283 normal3f = rsurface.modelnormal3f;
10285 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10287 index = 3*e[cornerindex];
10288 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10291 //TriangleNormal(v[0], v[1], v[2], normal);
10292 //if (DotProduct(normal, localnormal) < 0.0f)
10294 // clip by each of the box planes formed from the projection matrix
10295 // if anything survives, we emit the decal
10296 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]);
10299 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]);
10302 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]);
10305 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]);
10308 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]);
10311 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]);
10314 // some part of the triangle survived, so we have to accept it...
10317 // dynamic always uses the original triangle
10319 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10321 index = 3*e[cornerindex];
10322 VectorCopy(vertex3f + index, v[cornerindex]);
10325 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10327 // convert vertex positions to texcoords
10328 Matrix4x4_Transform(projection, v[cornerindex], temp);
10329 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10330 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10331 // calculate distance fade from the projection origin
10332 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10333 f = bound(0.0f, f, 1.0f);
10334 c[cornerindex][0] = r * f;
10335 c[cornerindex][1] = g * f;
10336 c[cornerindex][2] = b * f;
10337 c[cornerindex][3] = 1.0f;
10338 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10341 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);
10343 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10344 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);
10346 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)
10348 matrix4x4_t projection;
10349 decalsystem_t *decalsystem;
10352 const msurface_t *surface;
10353 const msurface_t *surfaces;
10354 const int *surfacelist;
10355 const texture_t *texture;
10357 int numsurfacelist;
10358 int surfacelistindex;
10361 float localorigin[3];
10362 float localnormal[3];
10363 float localmins[3];
10364 float localmaxs[3];
10367 float planes[6][4];
10370 int bih_triangles_count;
10371 int bih_triangles[256];
10372 int bih_surfaces[256];
10374 decalsystem = &ent->decalsystem;
10375 model = ent->model;
10376 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10378 R_DecalSystem_Reset(&ent->decalsystem);
10382 if (!model->brush.data_leafs && !cl_decals_models.integer)
10384 if (decalsystem->model)
10385 R_DecalSystem_Reset(decalsystem);
10389 if (decalsystem->model != model)
10390 R_DecalSystem_Reset(decalsystem);
10391 decalsystem->model = model;
10393 RSurf_ActiveModelEntity(ent, true, false, false);
10395 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10396 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10397 VectorNormalize(localnormal);
10398 localsize = worldsize*rsurface.inversematrixscale;
10399 localmins[0] = localorigin[0] - localsize;
10400 localmins[1] = localorigin[1] - localsize;
10401 localmins[2] = localorigin[2] - localsize;
10402 localmaxs[0] = localorigin[0] + localsize;
10403 localmaxs[1] = localorigin[1] + localsize;
10404 localmaxs[2] = localorigin[2] + localsize;
10406 //VectorCopy(localnormal, planes[4]);
10407 //VectorVectors(planes[4], planes[2], planes[0]);
10408 AnglesFromVectors(angles, localnormal, NULL, false);
10409 AngleVectors(angles, planes[0], planes[2], planes[4]);
10410 VectorNegate(planes[0], planes[1]);
10411 VectorNegate(planes[2], planes[3]);
10412 VectorNegate(planes[4], planes[5]);
10413 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10414 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10415 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10416 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10417 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10418 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10423 matrix4x4_t forwardprojection;
10424 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10425 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10430 float projectionvector[4][3];
10431 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10432 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10433 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10434 projectionvector[0][0] = planes[0][0] * ilocalsize;
10435 projectionvector[0][1] = planes[1][0] * ilocalsize;
10436 projectionvector[0][2] = planes[2][0] * ilocalsize;
10437 projectionvector[1][0] = planes[0][1] * ilocalsize;
10438 projectionvector[1][1] = planes[1][1] * ilocalsize;
10439 projectionvector[1][2] = planes[2][1] * ilocalsize;
10440 projectionvector[2][0] = planes[0][2] * ilocalsize;
10441 projectionvector[2][1] = planes[1][2] * ilocalsize;
10442 projectionvector[2][2] = planes[2][2] * ilocalsize;
10443 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10444 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10445 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10446 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10450 dynamic = model->surfmesh.isanimated;
10451 numsurfacelist = model->nummodelsurfaces;
10452 surfacelist = model->sortedmodelsurfaces;
10453 surfaces = model->data_surfaces;
10456 bih_triangles_count = -1;
10459 if(model->render_bih.numleafs)
10460 bih = &model->render_bih;
10461 else if(model->collision_bih.numleafs)
10462 bih = &model->collision_bih;
10465 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10466 if(bih_triangles_count == 0)
10468 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10470 if(bih_triangles_count > 0)
10472 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10474 surfaceindex = bih_surfaces[triangleindex];
10475 surface = surfaces + surfaceindex;
10476 texture = surface->texture;
10477 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10479 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10481 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10486 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10488 surfaceindex = surfacelist[surfacelistindex];
10489 surface = surfaces + surfaceindex;
10490 // check cull box first because it rejects more than any other check
10491 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10493 // skip transparent surfaces
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 numtriangles = surface->num_triangles;
10500 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10501 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10506 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10507 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)
10509 int renderentityindex;
10510 float worldmins[3];
10511 float worldmaxs[3];
10512 entity_render_t *ent;
10514 if (!cl_decals_newsystem.integer)
10517 worldmins[0] = worldorigin[0] - worldsize;
10518 worldmins[1] = worldorigin[1] - worldsize;
10519 worldmins[2] = worldorigin[2] - worldsize;
10520 worldmaxs[0] = worldorigin[0] + worldsize;
10521 worldmaxs[1] = worldorigin[1] + worldsize;
10522 worldmaxs[2] = worldorigin[2] + worldsize;
10524 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10526 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10528 ent = r_refdef.scene.entities[renderentityindex];
10529 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10532 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10536 typedef struct r_decalsystem_splatqueue_s
10538 vec3_t worldorigin;
10539 vec3_t worldnormal;
10545 r_decalsystem_splatqueue_t;
10547 int r_decalsystem_numqueued = 0;
10548 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10550 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)
10552 r_decalsystem_splatqueue_t *queue;
10554 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10557 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10558 VectorCopy(worldorigin, queue->worldorigin);
10559 VectorCopy(worldnormal, queue->worldnormal);
10560 Vector4Set(queue->color, r, g, b, a);
10561 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10562 queue->worldsize = worldsize;
10563 queue->decalsequence = cl.decalsequence++;
10566 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10569 r_decalsystem_splatqueue_t *queue;
10571 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10572 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);
10573 r_decalsystem_numqueued = 0;
10576 extern cvar_t cl_decals_max;
10577 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10580 decalsystem_t *decalsystem = &ent->decalsystem;
10587 if (!decalsystem->numdecals)
10590 if (r_showsurfaces.integer)
10593 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10595 R_DecalSystem_Reset(decalsystem);
10599 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10600 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10602 if (decalsystem->lastupdatetime)
10603 frametime = (cl.time - decalsystem->lastupdatetime);
10606 decalsystem->lastupdatetime = cl.time;
10607 decal = decalsystem->decals;
10608 numdecals = decalsystem->numdecals;
10610 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10612 if (decal->color4f[0][3])
10614 decal->lived += frametime;
10615 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10617 memset(decal, 0, sizeof(*decal));
10618 if (decalsystem->freedecal > i)
10619 decalsystem->freedecal = i;
10623 decal = decalsystem->decals;
10624 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10627 // collapse the array by shuffling the tail decals into the gaps
10630 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10631 decalsystem->freedecal++;
10632 if (decalsystem->freedecal == numdecals)
10634 decal[decalsystem->freedecal] = decal[--numdecals];
10637 decalsystem->numdecals = numdecals;
10639 if (numdecals <= 0)
10641 // if there are no decals left, reset decalsystem
10642 R_DecalSystem_Reset(decalsystem);
10646 extern skinframe_t *decalskinframe;
10647 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10650 decalsystem_t *decalsystem = &ent->decalsystem;
10659 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10662 numdecals = decalsystem->numdecals;
10666 if (r_showsurfaces.integer)
10669 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10671 R_DecalSystem_Reset(decalsystem);
10675 // if the model is static it doesn't matter what value we give for
10676 // wantnormals and wanttangents, so this logic uses only rules applicable
10677 // to a model, knowing that they are meaningless otherwise
10678 if (ent == r_refdef.scene.worldentity)
10679 RSurf_ActiveWorldEntity();
10681 RSurf_ActiveModelEntity(ent, false, false, false);
10683 decalsystem->lastupdatetime = cl.time;
10684 decal = decalsystem->decals;
10686 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10688 // update vertex positions for animated models
10689 v3f = decalsystem->vertex3f;
10690 c4f = decalsystem->color4f;
10691 t2f = decalsystem->texcoord2f;
10692 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10694 if (!decal->color4f[0][3])
10697 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10700 // update color values for fading decals
10701 if (decal->lived >= cl_decals_time.value)
10702 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10706 c4f[ 0] = decal->color4f[0][0] * alpha;
10707 c4f[ 1] = decal->color4f[0][1] * alpha;
10708 c4f[ 2] = decal->color4f[0][2] * alpha;
10710 c4f[ 4] = decal->color4f[1][0] * alpha;
10711 c4f[ 5] = decal->color4f[1][1] * alpha;
10712 c4f[ 6] = decal->color4f[1][2] * alpha;
10714 c4f[ 8] = decal->color4f[2][0] * alpha;
10715 c4f[ 9] = decal->color4f[2][1] * alpha;
10716 c4f[10] = decal->color4f[2][2] * alpha;
10719 t2f[0] = decal->texcoord2f[0][0];
10720 t2f[1] = decal->texcoord2f[0][1];
10721 t2f[2] = decal->texcoord2f[1][0];
10722 t2f[3] = decal->texcoord2f[1][1];
10723 t2f[4] = decal->texcoord2f[2][0];
10724 t2f[5] = decal->texcoord2f[2][1];
10726 // update vertex positions for animated models
10727 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10729 e = rsurface.modelelement3i + 3*decal->triangleindex;
10730 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10731 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10732 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10736 VectorCopy(decal->vertex3f[0], v3f);
10737 VectorCopy(decal->vertex3f[1], v3f + 3);
10738 VectorCopy(decal->vertex3f[2], v3f + 6);
10741 if (r_refdef.fogenabled)
10743 alpha = RSurf_FogVertex(v3f);
10744 VectorScale(c4f, alpha, c4f);
10745 alpha = RSurf_FogVertex(v3f + 3);
10746 VectorScale(c4f + 4, alpha, c4f + 4);
10747 alpha = RSurf_FogVertex(v3f + 6);
10748 VectorScale(c4f + 8, alpha, c4f + 8);
10759 r_refdef.stats.drawndecals += numtris;
10761 // now render the decals all at once
10762 // (this assumes they all use one particle font texture!)
10763 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);
10764 // R_Mesh_ResetTextureState();
10765 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10766 GL_DepthMask(false);
10767 GL_DepthRange(0, 1);
10768 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10769 GL_DepthTest(true);
10770 GL_CullFace(GL_NONE);
10771 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10772 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10773 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10777 static void R_DrawModelDecals(void)
10781 // fade faster when there are too many decals
10782 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10783 for (i = 0;i < r_refdef.scene.numentities;i++)
10784 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10786 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10787 for (i = 0;i < r_refdef.scene.numentities;i++)
10788 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10789 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10791 R_DecalSystem_ApplySplatEntitiesQueue();
10793 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10794 for (i = 0;i < r_refdef.scene.numentities;i++)
10795 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10797 r_refdef.stats.totaldecals += numdecals;
10799 if (r_showsurfaces.integer)
10802 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10804 for (i = 0;i < r_refdef.scene.numentities;i++)
10806 if (!r_refdef.viewcache.entityvisible[i])
10808 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10809 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10813 extern cvar_t mod_collision_bih;
10814 void R_DrawDebugModel(void)
10816 entity_render_t *ent = rsurface.entity;
10817 int i, j, k, l, flagsmask;
10818 const msurface_t *surface;
10819 dp_model_t *model = ent->model;
10822 switch(vid.renderpath)
10824 case RENDERPATH_GL11:
10825 case RENDERPATH_GL13:
10826 case RENDERPATH_GL20:
10828 case RENDERPATH_D3D9:
10829 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10831 case RENDERPATH_D3D10:
10832 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10834 case RENDERPATH_D3D11:
10835 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10837 case RENDERPATH_SOFT:
10838 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10840 case RENDERPATH_GLES2:
10841 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10845 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10847 // R_Mesh_ResetTextureState();
10848 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10849 GL_DepthRange(0, 1);
10850 GL_DepthTest(!r_showdisabledepthtest.integer);
10851 GL_DepthMask(false);
10852 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10854 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10858 qboolean cullbox = ent == r_refdef.scene.worldentity;
10859 const q3mbrush_t *brush;
10860 const bih_t *bih = &model->collision_bih;
10861 const bih_leaf_t *bihleaf;
10862 float vertex3f[3][3];
10863 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10865 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10867 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10869 switch (bihleaf->type)
10872 brush = model->brush.data_brushes + bihleaf->itemindex;
10873 if (brush->colbrushf && brush->colbrushf->numtriangles)
10875 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);
10876 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10877 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10880 case BIH_COLLISIONTRIANGLE:
10881 triangleindex = bihleaf->itemindex;
10882 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10883 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10884 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10885 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);
10886 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10887 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10889 case BIH_RENDERTRIANGLE:
10890 triangleindex = bihleaf->itemindex;
10891 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10892 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10893 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10894 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);
10895 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10896 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10902 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10904 if (r_showtris.integer || (r_shownormals.value != 0))
10906 if (r_showdisabledepthtest.integer)
10908 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10909 GL_DepthMask(false);
10913 GL_BlendFunc(GL_ONE, GL_ZERO);
10914 GL_DepthMask(true);
10916 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10918 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10920 rsurface.texture = R_GetCurrentTexture(surface->texture);
10921 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10923 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10924 if (r_showtris.value > 0)
10926 if (!rsurface.texture->currentlayers->depthmask)
10927 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10928 else if (ent == r_refdef.scene.worldentity)
10929 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10931 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10932 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10933 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10935 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10938 if (r_shownormals.value < 0)
10940 qglBegin(GL_LINES);
10941 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10943 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10944 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10945 qglVertex3f(v[0], v[1], v[2]);
10946 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10947 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10948 qglVertex3f(v[0], v[1], v[2]);
10953 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10955 qglBegin(GL_LINES);
10956 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10958 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10959 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10960 qglVertex3f(v[0], v[1], v[2]);
10961 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10962 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10963 qglVertex3f(v[0], v[1], v[2]);
10967 qglBegin(GL_LINES);
10968 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10970 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10971 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10972 qglVertex3f(v[0], v[1], v[2]);
10973 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10974 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10975 qglVertex3f(v[0], v[1], v[2]);
10979 qglBegin(GL_LINES);
10980 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10982 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10983 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10984 qglVertex3f(v[0], v[1], v[2]);
10985 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10986 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10987 qglVertex3f(v[0], v[1], v[2]);
10994 rsurface.texture = NULL;
10998 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10999 int r_maxsurfacelist = 0;
11000 const msurface_t **r_surfacelist = NULL;
11001 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11003 int i, j, endj, flagsmask;
11004 dp_model_t *model = r_refdef.scene.worldmodel;
11005 msurface_t *surfaces;
11006 unsigned char *update;
11007 int numsurfacelist = 0;
11011 if (r_maxsurfacelist < model->num_surfaces)
11013 r_maxsurfacelist = model->num_surfaces;
11015 Mem_Free((msurface_t**)r_surfacelist);
11016 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11019 RSurf_ActiveWorldEntity();
11021 surfaces = model->data_surfaces;
11022 update = model->brushq1.lightmapupdateflags;
11024 // update light styles on this submodel
11025 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11027 model_brush_lightstyleinfo_t *style;
11028 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11030 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11032 int *list = style->surfacelist;
11033 style->value = r_refdef.scene.lightstylevalue[style->style];
11034 for (j = 0;j < style->numsurfaces;j++)
11035 update[list[j]] = true;
11040 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11044 R_DrawDebugModel();
11045 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11049 rsurface.lightmaptexture = NULL;
11050 rsurface.deluxemaptexture = NULL;
11051 rsurface.uselightmaptexture = false;
11052 rsurface.texture = NULL;
11053 rsurface.rtlight = NULL;
11054 numsurfacelist = 0;
11055 // add visible surfaces to draw list
11056 for (i = 0;i < model->nummodelsurfaces;i++)
11058 j = model->sortedmodelsurfaces[i];
11059 if (r_refdef.viewcache.world_surfacevisible[j])
11060 r_surfacelist[numsurfacelist++] = surfaces + j;
11062 // update lightmaps if needed
11063 if (model->brushq1.firstrender)
11065 model->brushq1.firstrender = false;
11066 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11068 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11072 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11073 if (r_refdef.viewcache.world_surfacevisible[j])
11075 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11077 // don't do anything if there were no surfaces
11078 if (!numsurfacelist)
11080 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11083 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11085 // add to stats if desired
11086 if (r_speeds.integer && !skysurfaces && !depthonly)
11088 r_refdef.stats.world_surfaces += numsurfacelist;
11089 for (j = 0;j < numsurfacelist;j++)
11090 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11093 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11096 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11098 int i, j, endj, flagsmask;
11099 dp_model_t *model = ent->model;
11100 msurface_t *surfaces;
11101 unsigned char *update;
11102 int numsurfacelist = 0;
11106 if (r_maxsurfacelist < model->num_surfaces)
11108 r_maxsurfacelist = model->num_surfaces;
11110 Mem_Free((msurface_t **)r_surfacelist);
11111 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11114 // if the model is static it doesn't matter what value we give for
11115 // wantnormals and wanttangents, so this logic uses only rules applicable
11116 // to a model, knowing that they are meaningless otherwise
11117 if (ent == r_refdef.scene.worldentity)
11118 RSurf_ActiveWorldEntity();
11119 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11120 RSurf_ActiveModelEntity(ent, false, false, false);
11122 RSurf_ActiveModelEntity(ent, true, true, true);
11123 else if (depthonly)
11125 switch (vid.renderpath)
11127 case RENDERPATH_GL20:
11128 case RENDERPATH_D3D9:
11129 case RENDERPATH_D3D10:
11130 case RENDERPATH_D3D11:
11131 case RENDERPATH_SOFT:
11132 case RENDERPATH_GLES2:
11133 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11135 case RENDERPATH_GL13:
11136 case RENDERPATH_GL11:
11137 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
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, true, true, false);
11153 case RENDERPATH_GL13:
11154 case RENDERPATH_GL11:
11155 RSurf_ActiveModelEntity(ent, true, false, false);
11160 surfaces = model->data_surfaces;
11161 update = model->brushq1.lightmapupdateflags;
11163 // update light styles
11164 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11166 model_brush_lightstyleinfo_t *style;
11167 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11169 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11171 int *list = style->surfacelist;
11172 style->value = r_refdef.scene.lightstylevalue[style->style];
11173 for (j = 0;j < style->numsurfaces;j++)
11174 update[list[j]] = true;
11179 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11183 R_DrawDebugModel();
11184 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11188 rsurface.lightmaptexture = NULL;
11189 rsurface.deluxemaptexture = NULL;
11190 rsurface.uselightmaptexture = false;
11191 rsurface.texture = NULL;
11192 rsurface.rtlight = NULL;
11193 numsurfacelist = 0;
11194 // add visible surfaces to draw list
11195 for (i = 0;i < model->nummodelsurfaces;i++)
11196 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11197 // don't do anything if there were no surfaces
11198 if (!numsurfacelist)
11200 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11203 // update lightmaps if needed
11207 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11212 R_BuildLightMap(ent, surfaces + j);
11217 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11219 R_BuildLightMap(ent, surfaces + j);
11220 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11222 // add to stats if desired
11223 if (r_speeds.integer && !skysurfaces && !depthonly)
11225 r_refdef.stats.entities_surfaces += numsurfacelist;
11226 for (j = 0;j < numsurfacelist;j++)
11227 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11230 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11233 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11235 static texture_t texture;
11236 static msurface_t surface;
11237 const msurface_t *surfacelist = &surface;
11239 // fake enough texture and surface state to render this geometry
11241 texture.update_lastrenderframe = -1; // regenerate this texture
11242 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11243 texture.currentskinframe = skinframe;
11244 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11245 texture.offsetmapping = OFFSETMAPPING_OFF;
11246 texture.offsetscale = 1;
11247 texture.specularscalemod = 1;
11248 texture.specularpowermod = 1;
11250 surface.texture = &texture;
11251 surface.num_triangles = numtriangles;
11252 surface.num_firsttriangle = firsttriangle;
11253 surface.num_vertices = numvertices;
11254 surface.num_firstvertex = firstvertex;
11257 rsurface.texture = R_GetCurrentTexture(surface.texture);
11258 rsurface.lightmaptexture = NULL;
11259 rsurface.deluxemaptexture = NULL;
11260 rsurface.uselightmaptexture = false;
11261 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11264 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)
11266 static msurface_t surface;
11267 const msurface_t *surfacelist = &surface;
11269 // fake enough texture and surface state to render this geometry
11270 surface.texture = texture;
11271 surface.num_triangles = numtriangles;
11272 surface.num_firsttriangle = firsttriangle;
11273 surface.num_vertices = numvertices;
11274 surface.num_firstvertex = firstvertex;
11277 rsurface.texture = R_GetCurrentTexture(surface.texture);
11278 rsurface.lightmaptexture = NULL;
11279 rsurface.deluxemaptexture = NULL;
11280 rsurface.uselightmaptexture = false;
11281 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);