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_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 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"};
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131 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)"};
132 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"};
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 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)"};
145 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
146 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)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
148 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)"};
149 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
150 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158 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)"};
160 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)"};
161 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
162 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"};
163 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
164 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
165 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
167 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
168 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
169 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
170 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
172 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
173 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
174 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
175 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
176 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
177 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
178 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
180 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
181 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
182 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
183 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)"};
184 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
185 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
186 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
188 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
189 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
191 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"};
193 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"};
195 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
197 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
198 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"};
199 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
200 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
201 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
202 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
203 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)"};
204 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
205 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
207 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
208 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"};
210 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)"};
212 extern cvar_t v_glslgamma;
214 extern qboolean v_flipped_state;
216 static struct r_bloomstate_s
221 int bloomwidth, bloomheight;
223 int screentexturewidth, screentextureheight;
224 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
226 int bloomtexturewidth, bloomtextureheight;
227 rtexture_t *texture_bloom;
229 // arrays for rendering the screen passes
230 float screentexcoord2f[8];
231 float bloomtexcoord2f[8];
232 float offsettexcoord2f[8];
234 r_viewport_t viewport;
238 r_waterstate_t r_waterstate;
240 /// shadow volume bsp struct with automatically growing nodes buffer
243 rtexture_t *r_texture_blanknormalmap;
244 rtexture_t *r_texture_white;
245 rtexture_t *r_texture_grey128;
246 rtexture_t *r_texture_black;
247 rtexture_t *r_texture_notexture;
248 rtexture_t *r_texture_whitecube;
249 rtexture_t *r_texture_normalizationcube;
250 rtexture_t *r_texture_fogattenuation;
251 rtexture_t *r_texture_fogheighttexture;
252 rtexture_t *r_texture_gammaramps;
253 unsigned int r_texture_gammaramps_serial;
254 //rtexture_t *r_texture_fogintensity;
255 rtexture_t *r_texture_reflectcube;
257 // TODO: hash lookups?
258 typedef struct cubemapinfo_s
265 int r_texture_numcubemaps;
266 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
268 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
269 unsigned int r_numqueries;
270 unsigned int r_maxqueries;
272 typedef struct r_qwskincache_s
274 char name[MAX_QPATH];
275 skinframe_t *skinframe;
279 static r_qwskincache_t *r_qwskincache;
280 static int r_qwskincache_size;
282 /// vertex coordinates for a quad that covers the screen exactly
283 extern const float r_screenvertex3f[12];
284 extern const float r_d3dscreenvertex3f[12];
285 const float r_screenvertex3f[12] =
292 const float r_d3dscreenvertex3f[12] =
300 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
303 for (i = 0;i < verts;i++)
314 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
317 for (i = 0;i < verts;i++)
327 // FIXME: move this to client?
330 if (gamemode == GAME_NEHAHRA)
332 Cvar_Set("gl_fogenable", "0");
333 Cvar_Set("gl_fogdensity", "0.2");
334 Cvar_Set("gl_fogred", "0.3");
335 Cvar_Set("gl_foggreen", "0.3");
336 Cvar_Set("gl_fogblue", "0.3");
338 r_refdef.fog_density = 0;
339 r_refdef.fog_red = 0;
340 r_refdef.fog_green = 0;
341 r_refdef.fog_blue = 0;
342 r_refdef.fog_alpha = 1;
343 r_refdef.fog_start = 0;
344 r_refdef.fog_end = 16384;
345 r_refdef.fog_height = 1<<30;
346 r_refdef.fog_fadedepth = 128;
347 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
350 static void R_BuildBlankTextures(void)
352 unsigned char data[4];
353 data[2] = 128; // normal X
354 data[1] = 128; // normal Y
355 data[0] = 255; // normal Z
356 data[3] = 128; // height
357 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
362 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
367 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375 static void R_BuildNoTexture(void)
378 unsigned char pix[16][16][4];
379 // this makes a light grey/dark grey checkerboard texture
380 for (y = 0;y < 16;y++)
382 for (x = 0;x < 16;x++)
384 if ((y < 8) ^ (x < 8))
400 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
403 static void R_BuildWhiteCube(void)
405 unsigned char data[6*1*1*4];
406 memset(data, 255, sizeof(data));
407 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
410 static void R_BuildNormalizationCube(void)
414 vec_t s, t, intensity;
417 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
418 for (side = 0;side < 6;side++)
420 for (y = 0;y < NORMSIZE;y++)
422 for (x = 0;x < NORMSIZE;x++)
424 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
425 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
460 intensity = 127.0f / sqrt(DotProduct(v, v));
461 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
462 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
463 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
464 data[((side*64+y)*64+x)*4+3] = 255;
468 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
472 static void R_BuildFogTexture(void)
476 unsigned char data1[FOGWIDTH][4];
477 //unsigned char data2[FOGWIDTH][4];
480 r_refdef.fogmasktable_start = r_refdef.fog_start;
481 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
482 r_refdef.fogmasktable_range = r_refdef.fogrange;
483 r_refdef.fogmasktable_density = r_refdef.fog_density;
485 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
486 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
488 d = (x * r - r_refdef.fogmasktable_start);
489 if(developer_extra.integer)
490 Con_DPrintf("%f ", d);
492 if (r_fog_exp2.integer)
493 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
495 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
496 if(developer_extra.integer)
497 Con_DPrintf(" : %f ", alpha);
498 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
499 if(developer_extra.integer)
500 Con_DPrintf(" = %f\n", alpha);
501 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
504 for (x = 0;x < FOGWIDTH;x++)
506 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
511 //data2[x][0] = 255 - b;
512 //data2[x][1] = 255 - b;
513 //data2[x][2] = 255 - b;
516 if (r_texture_fogattenuation)
518 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
519 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
523 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
524 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
528 static void R_BuildFogHeightTexture(void)
530 unsigned char *inpixels;
538 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
539 if (r_refdef.fogheighttexturename[0])
540 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
543 r_refdef.fog_height_tablesize = 0;
544 if (r_texture_fogheighttexture)
545 R_FreeTexture(r_texture_fogheighttexture);
546 r_texture_fogheighttexture = NULL;
547 if (r_refdef.fog_height_table2d)
548 Mem_Free(r_refdef.fog_height_table2d);
549 r_refdef.fog_height_table2d = NULL;
550 if (r_refdef.fog_height_table1d)
551 Mem_Free(r_refdef.fog_height_table1d);
552 r_refdef.fog_height_table1d = NULL;
556 r_refdef.fog_height_tablesize = size;
557 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
558 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
559 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
561 // LordHavoc: now the magic - what is that table2d for? it is a cooked
562 // average fog color table accounting for every fog layer between a point
563 // and the camera. (Note: attenuation is handled separately!)
564 for (y = 0;y < size;y++)
566 for (x = 0;x < size;x++)
572 for (j = x;j <= y;j++)
574 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580 for (j = x;j >= y;j--)
582 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
588 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
589 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
590 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
593 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
596 //=======================================================================================================================================================
598 static const char *builtinshaderstring =
599 #include "shader_glsl.h"
602 const char *builtinhlslshaderstring =
603 #include "shader_hlsl.h"
606 char *glslshaderstring = NULL;
607 char *hlslshaderstring = NULL;
609 //=======================================================================================================================================================
611 typedef struct shaderpermutationinfo_s
616 shaderpermutationinfo_t;
618 typedef struct shadermodeinfo_s
620 const char *vertexfilename;
621 const char *geometryfilename;
622 const char *fragmentfilename;
628 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
629 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
631 {"#define USEDIFFUSE\n", " diffuse"},
632 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
633 {"#define USEVIEWTINT\n", " viewtint"},
634 {"#define USECOLORMAPPING\n", " colormapping"},
635 {"#define USESATURATION\n", " saturation"},
636 {"#define USEFOGINSIDE\n", " foginside"},
637 {"#define USEFOGOUTSIDE\n", " fogoutside"},
638 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
639 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
640 {"#define USEGAMMARAMPS\n", " gammaramps"},
641 {"#define USECUBEFILTER\n", " cubefilter"},
642 {"#define USEGLOW\n", " glow"},
643 {"#define USEBLOOM\n", " bloom"},
644 {"#define USESPECULAR\n", " specular"},
645 {"#define USEPOSTPROCESSING\n", " postprocessing"},
646 {"#define USEREFLECTION\n", " reflection"},
647 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
648 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
649 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
650 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
651 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
652 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
653 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
654 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
655 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
656 {"#define USEALPHAKILL\n", " alphakill"},
657 {"#define USEREFLECTCUBE\n", " reflectcube"},
658 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
659 {"#define USEBOUNCEGRID\n", " bouncegrid"},
660 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
663 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
664 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
666 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
667 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
668 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
684 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
686 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
708 struct r_glsl_permutation_s *hashnext;
710 unsigned int permutation;
712 /// indicates if we have tried compiling this permutation already
714 /// 0 if compilation failed
716 // texture units assigned to each detected uniform
717 int tex_Texture_First;
718 int tex_Texture_Second;
719 int tex_Texture_GammaRamps;
720 int tex_Texture_Normal;
721 int tex_Texture_Color;
722 int tex_Texture_Gloss;
723 int tex_Texture_Glow;
724 int tex_Texture_SecondaryNormal;
725 int tex_Texture_SecondaryColor;
726 int tex_Texture_SecondaryGloss;
727 int tex_Texture_SecondaryGlow;
728 int tex_Texture_Pants;
729 int tex_Texture_Shirt;
730 int tex_Texture_FogHeightTexture;
731 int tex_Texture_FogMask;
732 int tex_Texture_Lightmap;
733 int tex_Texture_Deluxemap;
734 int tex_Texture_Attenuation;
735 int tex_Texture_Cube;
736 int tex_Texture_Refraction;
737 int tex_Texture_Reflection;
738 int tex_Texture_ShadowMap2D;
739 int tex_Texture_CubeProjection;
740 int tex_Texture_ScreenDepth;
741 int tex_Texture_ScreenNormalMap;
742 int tex_Texture_ScreenDiffuse;
743 int tex_Texture_ScreenSpecular;
744 int tex_Texture_ReflectMask;
745 int tex_Texture_ReflectCube;
746 int tex_Texture_BounceGrid;
747 /// locations of detected uniforms in program object, or -1 if not found
748 int loc_Texture_First;
749 int loc_Texture_Second;
750 int loc_Texture_GammaRamps;
751 int loc_Texture_Normal;
752 int loc_Texture_Color;
753 int loc_Texture_Gloss;
754 int loc_Texture_Glow;
755 int loc_Texture_SecondaryNormal;
756 int loc_Texture_SecondaryColor;
757 int loc_Texture_SecondaryGloss;
758 int loc_Texture_SecondaryGlow;
759 int loc_Texture_Pants;
760 int loc_Texture_Shirt;
761 int loc_Texture_FogHeightTexture;
762 int loc_Texture_FogMask;
763 int loc_Texture_Lightmap;
764 int loc_Texture_Deluxemap;
765 int loc_Texture_Attenuation;
766 int loc_Texture_Cube;
767 int loc_Texture_Refraction;
768 int loc_Texture_Reflection;
769 int loc_Texture_ShadowMap2D;
770 int loc_Texture_CubeProjection;
771 int loc_Texture_ScreenDepth;
772 int loc_Texture_ScreenNormalMap;
773 int loc_Texture_ScreenDiffuse;
774 int loc_Texture_ScreenSpecular;
775 int loc_Texture_ReflectMask;
776 int loc_Texture_ReflectCube;
777 int loc_Texture_BounceGrid;
779 int loc_BloomBlur_Parameters;
781 int loc_Color_Ambient;
782 int loc_Color_Diffuse;
783 int loc_Color_Specular;
787 int loc_DeferredColor_Ambient;
788 int loc_DeferredColor_Diffuse;
789 int loc_DeferredColor_Specular;
790 int loc_DeferredMod_Diffuse;
791 int loc_DeferredMod_Specular;
792 int loc_DistortScaleRefractReflect;
795 int loc_FogHeightFade;
797 int loc_FogPlaneViewDist;
798 int loc_FogRangeRecip;
801 int loc_LightPosition;
802 int loc_OffsetMapping_ScaleSteps;
804 int loc_ReflectColor;
805 int loc_ReflectFactor;
806 int loc_ReflectOffset;
807 int loc_RefractColor;
809 int loc_ScreenCenterRefractReflect;
810 int loc_ScreenScaleRefractReflect;
811 int loc_ScreenToDepth;
812 int loc_ShadowMap_Parameters;
813 int loc_ShadowMap_TextureScale;
814 int loc_SpecularPower;
819 int loc_ViewTintColor;
821 int loc_ModelToLight;
823 int loc_BackgroundTexMatrix;
824 int loc_ModelViewProjectionMatrix;
825 int loc_ModelViewMatrix;
826 int loc_PixelToScreenTexCoord;
827 int loc_ModelToReflectCube;
828 int loc_ShadowMapMatrix;
829 int loc_BloomColorSubtract;
830 int loc_NormalmapScrollBlend;
831 int loc_BounceGridMatrix;
832 int loc_BounceGridIntensity;
834 r_glsl_permutation_t;
836 #define SHADERPERMUTATION_HASHSIZE 256
839 // non-degradable "lightweight" shader parameters to keep the permutations simpler
840 // these can NOT degrade! only use for simple stuff
843 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
844 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
845 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
846 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
847 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
848 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
850 #define SHADERSTATICPARMS_COUNT 6
852 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
853 static int shaderstaticparms_count = 0;
855 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
856 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
857 qboolean R_CompileShader_CheckStaticParms(void)
859 static int r_compileshader_staticparms_save[1];
860 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
861 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
864 if (r_glsl_saturation_redcompensate.integer)
865 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
866 if (r_shadow_glossexact.integer)
867 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
868 if (r_glsl_postprocess.integer)
870 if (r_glsl_postprocess_uservec1_enable.integer)
871 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
872 if (r_glsl_postprocess_uservec2_enable.integer)
873 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
874 if (r_glsl_postprocess_uservec3_enable.integer)
875 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
876 if (r_glsl_postprocess_uservec4_enable.integer)
877 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
879 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
882 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
883 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
884 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
886 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
887 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
889 shaderstaticparms_count = 0;
892 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
893 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
894 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
895 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
896 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
897 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
900 /// information about each possible shader permutation
901 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
902 /// currently selected permutation
903 r_glsl_permutation_t *r_glsl_permutation;
904 /// storage for permutations linked in the hash table
905 memexpandablearray_t r_glsl_permutationarray;
907 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
909 //unsigned int hashdepth = 0;
910 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
911 r_glsl_permutation_t *p;
912 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
914 if (p->mode == mode && p->permutation == permutation)
916 //if (hashdepth > 10)
917 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
922 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
924 p->permutation = permutation;
925 p->hashnext = r_glsl_permutationhash[mode][hashindex];
926 r_glsl_permutationhash[mode][hashindex] = p;
927 //if (hashdepth > 10)
928 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
932 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
935 if (!filename || !filename[0])
937 if (!strcmp(filename, "glsl/default.glsl"))
939 if (!glslshaderstring)
941 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
942 if (glslshaderstring)
943 Con_DPrintf("Loading shaders from file %s...\n", filename);
945 glslshaderstring = (char *)builtinshaderstring;
947 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
948 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
951 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
954 if (printfromdisknotice)
955 Con_DPrintf("from disk %s... ", filename);
961 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
965 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
966 char *vertexstring, *geometrystring, *fragmentstring;
967 char permutationname[256];
968 int vertstrings_count = 0;
969 int geomstrings_count = 0;
970 int fragstrings_count = 0;
971 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
972 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
973 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
980 permutationname[0] = 0;
981 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
982 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
983 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
985 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
987 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
988 if(vid.support.gl20shaders130)
990 vertstrings_list[vertstrings_count++] = "#version 130\n";
991 geomstrings_list[geomstrings_count++] = "#version 130\n";
992 fragstrings_list[fragstrings_count++] = "#version 130\n";
993 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
994 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
995 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
998 // the first pretext is which type of shader to compile as
999 // (later these will all be bound together as a program object)
1000 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1001 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1002 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1004 // the second pretext is the mode (for example a light source)
1005 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1006 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1007 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1008 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1010 // now add all the permutation pretexts
1011 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1013 if (permutation & (1<<i))
1015 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1016 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1017 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1018 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1022 // keep line numbers correct
1023 vertstrings_list[vertstrings_count++] = "\n";
1024 geomstrings_list[geomstrings_count++] = "\n";
1025 fragstrings_list[fragstrings_count++] = "\n";
1030 R_CompileShader_AddStaticParms(mode, permutation);
1031 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1032 vertstrings_count += shaderstaticparms_count;
1033 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1034 geomstrings_count += shaderstaticparms_count;
1035 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1036 fragstrings_count += shaderstaticparms_count;
1038 // now append the shader text itself
1039 vertstrings_list[vertstrings_count++] = vertexstring;
1040 geomstrings_list[geomstrings_count++] = geometrystring;
1041 fragstrings_list[fragstrings_count++] = fragmentstring;
1043 // if any sources were NULL, clear the respective list
1045 vertstrings_count = 0;
1046 if (!geometrystring)
1047 geomstrings_count = 0;
1048 if (!fragmentstring)
1049 fragstrings_count = 0;
1051 // compile the shader program
1052 if (vertstrings_count + geomstrings_count + fragstrings_count)
1053 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1057 qglUseProgram(p->program);CHECKGLERROR
1058 // look up all the uniform variable names we care about, so we don't
1059 // have to look them up every time we set them
1061 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1062 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1063 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1064 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1065 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1066 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1067 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1068 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1069 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1070 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1071 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1072 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1073 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1074 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1075 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1076 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1077 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1078 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1079 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1080 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1081 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1082 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1083 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1084 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1085 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1086 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1087 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1088 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1089 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1090 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1091 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1092 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1093 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1094 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1095 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1096 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1097 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1098 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1099 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1100 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1101 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1102 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1103 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1104 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1105 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1106 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1107 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1108 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1109 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1110 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1111 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1112 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1113 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1114 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1115 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1116 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1117 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1118 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1119 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1120 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1121 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1122 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1123 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1124 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1125 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1126 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1127 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1128 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1129 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1130 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1131 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1132 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1133 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1134 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1135 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1136 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1137 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1138 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1139 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1140 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1141 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1142 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1143 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1144 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1145 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1146 // initialize the samplers to refer to the texture units we use
1147 p->tex_Texture_First = -1;
1148 p->tex_Texture_Second = -1;
1149 p->tex_Texture_GammaRamps = -1;
1150 p->tex_Texture_Normal = -1;
1151 p->tex_Texture_Color = -1;
1152 p->tex_Texture_Gloss = -1;
1153 p->tex_Texture_Glow = -1;
1154 p->tex_Texture_SecondaryNormal = -1;
1155 p->tex_Texture_SecondaryColor = -1;
1156 p->tex_Texture_SecondaryGloss = -1;
1157 p->tex_Texture_SecondaryGlow = -1;
1158 p->tex_Texture_Pants = -1;
1159 p->tex_Texture_Shirt = -1;
1160 p->tex_Texture_FogHeightTexture = -1;
1161 p->tex_Texture_FogMask = -1;
1162 p->tex_Texture_Lightmap = -1;
1163 p->tex_Texture_Deluxemap = -1;
1164 p->tex_Texture_Attenuation = -1;
1165 p->tex_Texture_Cube = -1;
1166 p->tex_Texture_Refraction = -1;
1167 p->tex_Texture_Reflection = -1;
1168 p->tex_Texture_ShadowMap2D = -1;
1169 p->tex_Texture_CubeProjection = -1;
1170 p->tex_Texture_ScreenDepth = -1;
1171 p->tex_Texture_ScreenNormalMap = -1;
1172 p->tex_Texture_ScreenDiffuse = -1;
1173 p->tex_Texture_ScreenSpecular = -1;
1174 p->tex_Texture_ReflectMask = -1;
1175 p->tex_Texture_ReflectCube = -1;
1176 p->tex_Texture_BounceGrid = -1;
1178 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1179 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1180 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1181 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1182 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1183 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1184 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1185 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1186 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1187 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1188 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1189 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1190 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1191 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1192 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1193 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1194 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1195 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1196 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1197 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1198 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1199 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1200 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1201 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1202 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1203 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1204 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1205 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1206 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1207 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1209 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1212 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1216 Mem_Free(vertexstring);
1218 Mem_Free(geometrystring);
1220 Mem_Free(fragmentstring);
1223 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1225 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1226 if (r_glsl_permutation != perm)
1228 r_glsl_permutation = perm;
1229 if (!r_glsl_permutation->program)
1231 if (!r_glsl_permutation->compiled)
1232 R_GLSL_CompilePermutation(perm, mode, permutation);
1233 if (!r_glsl_permutation->program)
1235 // remove features until we find a valid permutation
1237 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1239 // reduce i more quickly whenever it would not remove any bits
1240 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1241 if (!(permutation & j))
1244 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1245 if (!r_glsl_permutation->compiled)
1246 R_GLSL_CompilePermutation(perm, mode, permutation);
1247 if (r_glsl_permutation->program)
1250 if (i >= SHADERPERMUTATION_COUNT)
1252 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1253 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1254 qglUseProgram(0);CHECKGLERROR
1255 return; // no bit left to clear, entire mode is broken
1260 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1262 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1263 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1264 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1271 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1272 extern D3DCAPS9 vid_d3d9caps;
1275 struct r_hlsl_permutation_s;
1276 typedef struct r_hlsl_permutation_s
1278 /// hash lookup data
1279 struct r_hlsl_permutation_s *hashnext;
1281 unsigned int permutation;
1283 /// indicates if we have tried compiling this permutation already
1285 /// NULL if compilation failed
1286 IDirect3DVertexShader9 *vertexshader;
1287 IDirect3DPixelShader9 *pixelshader;
1289 r_hlsl_permutation_t;
1291 typedef enum D3DVSREGISTER_e
1293 D3DVSREGISTER_TexMatrix = 0, // float4x4
1294 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1295 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1296 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1297 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1298 D3DVSREGISTER_ModelToLight = 20, // float4x4
1299 D3DVSREGISTER_EyePosition = 24,
1300 D3DVSREGISTER_FogPlane = 25,
1301 D3DVSREGISTER_LightDir = 26,
1302 D3DVSREGISTER_LightPosition = 27,
1306 typedef enum D3DPSREGISTER_e
1308 D3DPSREGISTER_Alpha = 0,
1309 D3DPSREGISTER_BloomBlur_Parameters = 1,
1310 D3DPSREGISTER_ClientTime = 2,
1311 D3DPSREGISTER_Color_Ambient = 3,
1312 D3DPSREGISTER_Color_Diffuse = 4,
1313 D3DPSREGISTER_Color_Specular = 5,
1314 D3DPSREGISTER_Color_Glow = 6,
1315 D3DPSREGISTER_Color_Pants = 7,
1316 D3DPSREGISTER_Color_Shirt = 8,
1317 D3DPSREGISTER_DeferredColor_Ambient = 9,
1318 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1319 D3DPSREGISTER_DeferredColor_Specular = 11,
1320 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1321 D3DPSREGISTER_DeferredMod_Specular = 13,
1322 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1323 D3DPSREGISTER_EyePosition = 15, // unused
1324 D3DPSREGISTER_FogColor = 16,
1325 D3DPSREGISTER_FogHeightFade = 17,
1326 D3DPSREGISTER_FogPlane = 18,
1327 D3DPSREGISTER_FogPlaneViewDist = 19,
1328 D3DPSREGISTER_FogRangeRecip = 20,
1329 D3DPSREGISTER_LightColor = 21,
1330 D3DPSREGISTER_LightDir = 22, // unused
1331 D3DPSREGISTER_LightPosition = 23,
1332 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1333 D3DPSREGISTER_PixelSize = 25,
1334 D3DPSREGISTER_ReflectColor = 26,
1335 D3DPSREGISTER_ReflectFactor = 27,
1336 D3DPSREGISTER_ReflectOffset = 28,
1337 D3DPSREGISTER_RefractColor = 29,
1338 D3DPSREGISTER_Saturation = 30,
1339 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1340 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1341 D3DPSREGISTER_ScreenToDepth = 33,
1342 D3DPSREGISTER_ShadowMap_Parameters = 34,
1343 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1344 D3DPSREGISTER_SpecularPower = 36,
1345 D3DPSREGISTER_UserVec1 = 37,
1346 D3DPSREGISTER_UserVec2 = 38,
1347 D3DPSREGISTER_UserVec3 = 39,
1348 D3DPSREGISTER_UserVec4 = 40,
1349 D3DPSREGISTER_ViewTintColor = 41,
1350 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1351 D3DPSREGISTER_BloomColorSubtract = 43,
1352 D3DPSREGISTER_ViewToLight = 44, // float4x4
1353 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1354 D3DPSREGISTER_NormalmapScrollBlend = 52,
1359 /// information about each possible shader permutation
1360 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1361 /// currently selected permutation
1362 r_hlsl_permutation_t *r_hlsl_permutation;
1363 /// storage for permutations linked in the hash table
1364 memexpandablearray_t r_hlsl_permutationarray;
1366 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1368 //unsigned int hashdepth = 0;
1369 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1370 r_hlsl_permutation_t *p;
1371 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1373 if (p->mode == mode && p->permutation == permutation)
1375 //if (hashdepth > 10)
1376 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1381 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1383 p->permutation = permutation;
1384 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1385 r_hlsl_permutationhash[mode][hashindex] = p;
1386 //if (hashdepth > 10)
1387 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1391 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1394 if (!filename || !filename[0])
1396 if (!strcmp(filename, "hlsl/default.hlsl"))
1398 if (!hlslshaderstring)
1400 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1401 if (hlslshaderstring)
1402 Con_DPrintf("Loading shaders from file %s...\n", filename);
1404 hlslshaderstring = (char *)builtinhlslshaderstring;
1406 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1407 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1408 return shaderstring;
1410 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1413 if (printfromdisknotice)
1414 Con_DPrintf("from disk %s... ", filename);
1415 return shaderstring;
1417 return shaderstring;
1421 //#include <d3dx9shader.h>
1422 //#include <d3dx9mesh.h>
1424 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1426 DWORD *vsbin = NULL;
1427 DWORD *psbin = NULL;
1428 fs_offset_t vsbinsize;
1429 fs_offset_t psbinsize;
1430 // IDirect3DVertexShader9 *vs = NULL;
1431 // IDirect3DPixelShader9 *ps = NULL;
1432 ID3DXBuffer *vslog = NULL;
1433 ID3DXBuffer *vsbuffer = NULL;
1434 ID3DXConstantTable *vsconstanttable = NULL;
1435 ID3DXBuffer *pslog = NULL;
1436 ID3DXBuffer *psbuffer = NULL;
1437 ID3DXConstantTable *psconstanttable = NULL;
1440 char temp[MAX_INPUTLINE];
1441 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1442 qboolean debugshader = gl_paranoid.integer != 0;
1443 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1444 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1447 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1448 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1450 if ((!vsbin && vertstring) || (!psbin && fragstring))
1452 const char* dllnames_d3dx9 [] =
1476 dllhandle_t d3dx9_dll = NULL;
1477 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1478 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1479 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1480 dllfunction_t d3dx9_dllfuncs[] =
1482 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1483 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1484 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1487 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1489 DWORD shaderflags = 0;
1491 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1492 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1493 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1494 if (vertstring && vertstring[0])
1498 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1499 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1500 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1501 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1504 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1507 vsbinsize = vsbuffer->GetBufferSize();
1508 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1509 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1510 vsbuffer->Release();
1514 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1515 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1519 if (fragstring && fragstring[0])
1523 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1524 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1525 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1526 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1529 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1532 psbinsize = psbuffer->GetBufferSize();
1533 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1534 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1535 psbuffer->Release();
1539 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1540 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1544 Sys_UnloadLibrary(&d3dx9_dll);
1547 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1551 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1552 if (FAILED(vsresult))
1553 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1554 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1555 if (FAILED(psresult))
1556 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1558 // free the shader data
1559 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1560 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1563 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1566 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1567 int vertstring_length = 0;
1568 int geomstring_length = 0;
1569 int fragstring_length = 0;
1571 char *vertexstring, *geometrystring, *fragmentstring;
1572 char *vertstring, *geomstring, *fragstring;
1573 char permutationname[256];
1574 char cachename[256];
1575 int vertstrings_count = 0;
1576 int geomstrings_count = 0;
1577 int fragstrings_count = 0;
1578 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1579 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1580 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1585 p->vertexshader = NULL;
1586 p->pixelshader = NULL;
1588 permutationname[0] = 0;
1590 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1591 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1592 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1594 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1595 strlcat(cachename, "hlsl/", sizeof(cachename));
1597 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1598 vertstrings_count = 0;
1599 geomstrings_count = 0;
1600 fragstrings_count = 0;
1601 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1602 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1603 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1605 // the first pretext is which type of shader to compile as
1606 // (later these will all be bound together as a program object)
1607 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1608 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1609 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1611 // the second pretext is the mode (for example a light source)
1612 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1613 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1614 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1615 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1616 strlcat(cachename, modeinfo->name, sizeof(cachename));
1618 // now add all the permutation pretexts
1619 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1621 if (permutation & (1<<i))
1623 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1624 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1625 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1626 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1627 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1631 // keep line numbers correct
1632 vertstrings_list[vertstrings_count++] = "\n";
1633 geomstrings_list[geomstrings_count++] = "\n";
1634 fragstrings_list[fragstrings_count++] = "\n";
1639 R_CompileShader_AddStaticParms(mode, permutation);
1640 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1641 vertstrings_count += shaderstaticparms_count;
1642 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1643 geomstrings_count += shaderstaticparms_count;
1644 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1645 fragstrings_count += shaderstaticparms_count;
1647 // replace spaces in the cachename with _ characters
1648 for (i = 0;cachename[i];i++)
1649 if (cachename[i] == ' ')
1652 // now append the shader text itself
1653 vertstrings_list[vertstrings_count++] = vertexstring;
1654 geomstrings_list[geomstrings_count++] = geometrystring;
1655 fragstrings_list[fragstrings_count++] = fragmentstring;
1657 // if any sources were NULL, clear the respective list
1659 vertstrings_count = 0;
1660 if (!geometrystring)
1661 geomstrings_count = 0;
1662 if (!fragmentstring)
1663 fragstrings_count = 0;
1665 vertstring_length = 0;
1666 for (i = 0;i < vertstrings_count;i++)
1667 vertstring_length += strlen(vertstrings_list[i]);
1668 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1669 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1670 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1672 geomstring_length = 0;
1673 for (i = 0;i < geomstrings_count;i++)
1674 geomstring_length += strlen(geomstrings_list[i]);
1675 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1676 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1677 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1679 fragstring_length = 0;
1680 for (i = 0;i < fragstrings_count;i++)
1681 fragstring_length += strlen(fragstrings_list[i]);
1682 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1683 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1684 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1686 // try to load the cached shader, or generate one
1687 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1689 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1690 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1692 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1696 Mem_Free(vertstring);
1698 Mem_Free(geomstring);
1700 Mem_Free(fragstring);
1702 Mem_Free(vertexstring);
1704 Mem_Free(geometrystring);
1706 Mem_Free(fragmentstring);
1709 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1710 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1711 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);}
1712 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);}
1713 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);}
1714 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);}
1716 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1717 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1718 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);}
1719 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);}
1720 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);}
1721 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);}
1723 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1725 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1726 if (r_hlsl_permutation != perm)
1728 r_hlsl_permutation = perm;
1729 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1731 if (!r_hlsl_permutation->compiled)
1732 R_HLSL_CompilePermutation(perm, mode, permutation);
1733 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1735 // remove features until we find a valid permutation
1737 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1739 // reduce i more quickly whenever it would not remove any bits
1740 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1741 if (!(permutation & j))
1744 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1745 if (!r_hlsl_permutation->compiled)
1746 R_HLSL_CompilePermutation(perm, mode, permutation);
1747 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1750 if (i >= SHADERPERMUTATION_COUNT)
1752 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1753 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1754 return; // no bit left to clear, entire mode is broken
1758 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1759 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1761 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1762 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1763 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1767 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1769 DPSOFTRAST_SetShader(mode, permutation);
1770 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1771 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1772 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1775 void R_GLSL_Restart_f(void)
1777 unsigned int i, limit;
1778 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1779 Mem_Free(glslshaderstring);
1780 glslshaderstring = NULL;
1781 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1782 Mem_Free(hlslshaderstring);
1783 hlslshaderstring = NULL;
1784 switch(vid.renderpath)
1786 case RENDERPATH_D3D9:
1789 r_hlsl_permutation_t *p;
1790 r_hlsl_permutation = NULL;
1791 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1792 for (i = 0;i < limit;i++)
1794 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1796 if (p->vertexshader)
1797 IDirect3DVertexShader9_Release(p->vertexshader);
1799 IDirect3DPixelShader9_Release(p->pixelshader);
1800 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1803 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1807 case RENDERPATH_D3D10:
1808 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1810 case RENDERPATH_D3D11:
1811 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1813 case RENDERPATH_GL20:
1814 case RENDERPATH_GLES2:
1816 r_glsl_permutation_t *p;
1817 r_glsl_permutation = NULL;
1818 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1819 for (i = 0;i < limit;i++)
1821 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1823 GL_Backend_FreeProgram(p->program);
1824 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1827 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1830 case RENDERPATH_GL13:
1831 case RENDERPATH_GL11:
1833 case RENDERPATH_SOFT:
1838 void R_GLSL_DumpShader_f(void)
1843 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1846 FS_Print(file, "/* The engine may define the following macros:\n");
1847 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1848 for (i = 0;i < SHADERMODE_COUNT;i++)
1849 FS_Print(file, glslshadermodeinfo[i].pretext);
1850 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1851 FS_Print(file, shaderpermutationinfo[i].pretext);
1852 FS_Print(file, "*/\n");
1853 FS_Print(file, builtinshaderstring);
1855 Con_Printf("glsl/default.glsl written\n");
1858 Con_Printf("failed to write to glsl/default.glsl\n");
1860 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1863 FS_Print(file, "/* The engine may define the following macros:\n");
1864 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1865 for (i = 0;i < SHADERMODE_COUNT;i++)
1866 FS_Print(file, hlslshadermodeinfo[i].pretext);
1867 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1868 FS_Print(file, shaderpermutationinfo[i].pretext);
1869 FS_Print(file, "*/\n");
1870 FS_Print(file, builtinhlslshaderstring);
1872 Con_Printf("hlsl/default.hlsl written\n");
1875 Con_Printf("failed to write to hlsl/default.hlsl\n");
1878 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1881 texturemode = GL_MODULATE;
1882 switch (vid.renderpath)
1884 case RENDERPATH_D3D9:
1886 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))));
1887 R_Mesh_TexBind(GL20TU_FIRST , first );
1888 R_Mesh_TexBind(GL20TU_SECOND, second);
1891 case RENDERPATH_D3D10:
1892 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1894 case RENDERPATH_D3D11:
1895 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1897 case RENDERPATH_GL20:
1898 case RENDERPATH_GLES2:
1899 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))));
1900 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1901 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1903 case RENDERPATH_GL13:
1904 R_Mesh_TexBind(0, first );
1905 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1906 R_Mesh_TexBind(1, second);
1908 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1910 case RENDERPATH_GL11:
1911 R_Mesh_TexBind(0, first );
1913 case RENDERPATH_SOFT:
1914 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))));
1915 R_Mesh_TexBind(GL20TU_FIRST , first );
1916 R_Mesh_TexBind(GL20TU_SECOND, second);
1921 void R_SetupShader_DepthOrShadow(void)
1923 switch (vid.renderpath)
1925 case RENDERPATH_D3D9:
1927 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1930 case RENDERPATH_D3D10:
1931 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1933 case RENDERPATH_D3D11:
1934 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1936 case RENDERPATH_GL20:
1937 case RENDERPATH_GLES2:
1938 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1940 case RENDERPATH_GL13:
1941 R_Mesh_TexBind(0, 0);
1942 R_Mesh_TexBind(1, 0);
1944 case RENDERPATH_GL11:
1945 R_Mesh_TexBind(0, 0);
1947 case RENDERPATH_SOFT:
1948 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1953 void R_SetupShader_ShowDepth(void)
1955 switch (vid.renderpath)
1957 case RENDERPATH_D3D9:
1959 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1962 case RENDERPATH_D3D10:
1963 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1965 case RENDERPATH_D3D11:
1966 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1968 case RENDERPATH_GL20:
1969 case RENDERPATH_GLES2:
1970 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1972 case RENDERPATH_GL13:
1974 case RENDERPATH_GL11:
1976 case RENDERPATH_SOFT:
1977 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1982 extern qboolean r_shadow_usingdeferredprepass;
1983 extern cvar_t r_shadow_deferred_8bitrange;
1984 extern rtexture_t *r_shadow_attenuationgradienttexture;
1985 extern rtexture_t *r_shadow_attenuation2dtexture;
1986 extern rtexture_t *r_shadow_attenuation3dtexture;
1987 extern qboolean r_shadow_usingshadowmap2d;
1988 extern qboolean r_shadow_usingshadowmaportho;
1989 extern float r_shadow_shadowmap_texturescale[2];
1990 extern float r_shadow_shadowmap_parameters[4];
1991 extern qboolean r_shadow_shadowmapvsdct;
1992 extern qboolean r_shadow_shadowmapsampler;
1993 extern int r_shadow_shadowmappcf;
1994 extern rtexture_t *r_shadow_shadowmap2dtexture;
1995 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1996 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1997 extern matrix4x4_t r_shadow_shadowmapmatrix;
1998 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1999 extern int r_shadow_prepass_width;
2000 extern int r_shadow_prepass_height;
2001 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2002 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2003 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2004 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2005 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2007 #define BLENDFUNC_ALLOWS_COLORMOD 1
2008 #define BLENDFUNC_ALLOWS_FOG 2
2009 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2010 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2011 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2012 static int R_BlendFuncFlags(int src, int dst)
2016 // a blendfunc allows colormod if:
2017 // a) it can never keep the destination pixel invariant, or
2018 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2019 // this is to prevent unintended side effects from colormod
2021 // a blendfunc allows fog if:
2022 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2023 // this is to prevent unintended side effects from fog
2025 // these checks are the output of fogeval.pl
2027 r |= BLENDFUNC_ALLOWS_COLORMOD;
2028 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2029 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2030 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2031 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2032 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2033 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2034 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2035 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2036 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2037 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2038 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2039 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2040 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2041 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2043 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2044 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2045 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2046 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2047 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2048 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053 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)
2055 // select a permutation of the lighting shader appropriate to this
2056 // combination of texture, entity, light source, and fogging, only use the
2057 // minimum features necessary to avoid wasting rendering time in the
2058 // fragment shader on features that are not being used
2059 unsigned int permutation = 0;
2060 unsigned int mode = 0;
2062 static float dummy_colormod[3] = {1, 1, 1};
2063 float *colormod = rsurface.colormod;
2065 matrix4x4_t tempmatrix;
2066 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2067 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2068 permutation |= SHADERPERMUTATION_ALPHAKILL;
2069 if (rsurfacepass == RSURFPASS_BACKGROUND)
2071 // distorted background
2072 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2074 mode = SHADERMODE_WATER;
2075 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2076 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2077 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2079 // this is the right thing to do for wateralpha
2080 GL_BlendFunc(GL_ONE, GL_ZERO);
2081 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2085 // this is the right thing to do for entity alpha
2086 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2087 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2090 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2092 mode = SHADERMODE_REFRACTION;
2093 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2094 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2098 mode = SHADERMODE_GENERIC;
2099 permutation |= SHADERPERMUTATION_DIFFUSE;
2100 GL_BlendFunc(GL_ONE, GL_ZERO);
2101 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2104 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2106 if (r_glsl_offsetmapping.integer)
2108 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2109 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2110 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2111 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2112 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2114 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2115 if (r_glsl_offsetmapping_reliefmapping.integer)
2116 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2119 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2120 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2121 // normalmap (deferred prepass), may use alpha test on diffuse
2122 mode = SHADERMODE_DEFERREDGEOMETRY;
2123 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2124 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2125 GL_BlendFunc(GL_ONE, GL_ZERO);
2126 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2128 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2130 if (r_glsl_offsetmapping.integer)
2132 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2133 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2134 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2135 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2136 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2138 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2139 if (r_glsl_offsetmapping_reliefmapping.integer)
2140 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2146 mode = SHADERMODE_LIGHTSOURCE;
2147 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2148 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2149 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2150 permutation |= SHADERPERMUTATION_CUBEFILTER;
2151 if (diffusescale > 0)
2152 permutation |= SHADERPERMUTATION_DIFFUSE;
2153 if (specularscale > 0)
2154 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2155 if (r_refdef.fogenabled)
2156 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2157 if (rsurface.texture->colormapping)
2158 permutation |= SHADERPERMUTATION_COLORMAPPING;
2159 if (r_shadow_usingshadowmap2d)
2161 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2162 if(r_shadow_shadowmapvsdct)
2163 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2165 if (r_shadow_shadowmapsampler)
2166 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2167 if (r_shadow_shadowmappcf > 1)
2168 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2169 else if (r_shadow_shadowmappcf)
2170 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2172 if (rsurface.texture->reflectmasktexture)
2173 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2174 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2175 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2177 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2179 if (r_glsl_offsetmapping.integer)
2181 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2182 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2183 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2184 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2185 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2187 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2188 if (r_glsl_offsetmapping_reliefmapping.integer)
2189 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2192 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2193 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2194 // unshaded geometry (fullbright or ambient model lighting)
2195 mode = SHADERMODE_FLATCOLOR;
2196 ambientscale = diffusescale = specularscale = 0;
2197 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2198 permutation |= SHADERPERMUTATION_GLOW;
2199 if (r_refdef.fogenabled)
2200 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2201 if (rsurface.texture->colormapping)
2202 permutation |= SHADERPERMUTATION_COLORMAPPING;
2203 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2205 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2206 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2208 if (r_shadow_shadowmapsampler)
2209 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2210 if (r_shadow_shadowmappcf > 1)
2211 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2212 else if (r_shadow_shadowmappcf)
2213 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2216 permutation |= SHADERPERMUTATION_REFLECTION;
2217 if (rsurface.texture->reflectmasktexture)
2218 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2219 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2220 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2222 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2224 if (r_glsl_offsetmapping.integer)
2226 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2227 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2228 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2229 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2230 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2232 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2233 if (r_glsl_offsetmapping_reliefmapping.integer)
2234 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2237 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2238 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2239 // directional model lighting
2240 mode = SHADERMODE_LIGHTDIRECTION;
2241 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2242 permutation |= SHADERPERMUTATION_GLOW;
2243 permutation |= SHADERPERMUTATION_DIFFUSE;
2244 if (specularscale > 0)
2245 permutation |= SHADERPERMUTATION_SPECULAR;
2246 if (r_refdef.fogenabled)
2247 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2248 if (rsurface.texture->colormapping)
2249 permutation |= SHADERPERMUTATION_COLORMAPPING;
2250 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2252 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2253 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2255 if (r_shadow_shadowmapsampler)
2256 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2257 if (r_shadow_shadowmappcf > 1)
2258 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2259 else if (r_shadow_shadowmappcf)
2260 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2263 permutation |= SHADERPERMUTATION_REFLECTION;
2264 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2265 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2266 if (rsurface.texture->reflectmasktexture)
2267 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2268 if (r_shadow_bouncegridtexture)
2270 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2271 if (r_shadow_bouncegriddirectional)
2272 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2274 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2275 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2277 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2279 if (r_glsl_offsetmapping.integer)
2281 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2282 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2283 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2284 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2285 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2287 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2288 if (r_glsl_offsetmapping_reliefmapping.integer)
2289 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2293 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2294 // ambient model lighting
2295 mode = SHADERMODE_LIGHTDIRECTION;
2296 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2297 permutation |= SHADERPERMUTATION_GLOW;
2298 if (r_refdef.fogenabled)
2299 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300 if (rsurface.texture->colormapping)
2301 permutation |= SHADERPERMUTATION_COLORMAPPING;
2302 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307 if (r_shadow_shadowmapsampler)
2308 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2309 if (r_shadow_shadowmappcf > 1)
2310 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2311 else if (r_shadow_shadowmappcf)
2312 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2315 permutation |= SHADERPERMUTATION_REFLECTION;
2316 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2317 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2318 if (rsurface.texture->reflectmasktexture)
2319 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320 if (r_shadow_bouncegridtexture)
2322 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2323 if (r_shadow_bouncegriddirectional)
2324 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2326 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2331 if (r_glsl_offsetmapping.integer)
2333 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2334 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2335 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2336 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2337 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2339 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2340 if (r_glsl_offsetmapping_reliefmapping.integer)
2341 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2344 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2345 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2347 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2348 permutation |= SHADERPERMUTATION_GLOW;
2349 if (r_refdef.fogenabled)
2350 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2351 if (rsurface.texture->colormapping)
2352 permutation |= SHADERPERMUTATION_COLORMAPPING;
2353 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2355 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2356 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2358 if (r_shadow_shadowmapsampler)
2359 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2360 if (r_shadow_shadowmappcf > 1)
2361 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2362 else if (r_shadow_shadowmappcf)
2363 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2365 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2366 permutation |= SHADERPERMUTATION_REFLECTION;
2367 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2368 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2369 if (rsurface.texture->reflectmasktexture)
2370 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2371 if (FAKELIGHT_ENABLED)
2373 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2374 mode = SHADERMODE_FAKELIGHT;
2375 permutation |= SHADERPERMUTATION_DIFFUSE;
2376 if (specularscale > 0)
2377 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2379 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2381 // deluxemapping (light direction texture)
2382 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2383 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2385 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2386 permutation |= SHADERPERMUTATION_DIFFUSE;
2387 if (specularscale > 0)
2388 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2390 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2392 // fake deluxemapping (uniform light direction in tangentspace)
2393 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2394 permutation |= SHADERPERMUTATION_DIFFUSE;
2395 if (specularscale > 0)
2396 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2398 else if (rsurface.uselightmaptexture)
2400 // ordinary lightmapping (q1bsp, q3bsp)
2401 mode = SHADERMODE_LIGHTMAP;
2405 // ordinary vertex coloring (q3bsp)
2406 mode = SHADERMODE_VERTEXCOLOR;
2408 if (r_shadow_bouncegridtexture)
2410 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2411 if (r_shadow_bouncegriddirectional)
2412 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2414 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2418 colormod = dummy_colormod;
2419 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2420 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2421 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2422 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2423 switch(vid.renderpath)
2425 case RENDERPATH_D3D9:
2427 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);
2428 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2429 R_SetupShader_SetPermutationHLSL(mode, permutation);
2430 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2431 if (mode == SHADERMODE_LIGHTSOURCE)
2433 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2434 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2438 if (mode == SHADERMODE_LIGHTDIRECTION)
2440 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2443 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2444 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2445 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2446 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2447 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2449 if (mode == SHADERMODE_LIGHTSOURCE)
2451 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2452 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2453 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2454 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2455 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2457 // additive passes are only darkened by fog, not tinted
2458 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2459 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2463 if (mode == SHADERMODE_FLATCOLOR)
2465 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2467 else if (mode == SHADERMODE_LIGHTDIRECTION)
2469 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]);
2470 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2471 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);
2472 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);
2473 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2474 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2479 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2480 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2481 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);
2482 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);
2483 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2485 // additive passes are only darkened by fog, not tinted
2486 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2487 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2489 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2490 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);
2491 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2492 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2493 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2494 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2495 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2496 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2497 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2498 if (mode == SHADERMODE_WATER)
2499 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2501 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2502 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2503 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2504 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));
2505 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2506 if (rsurface.texture->pantstexture)
2507 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2510 if (rsurface.texture->shirttexture)
2511 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2514 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2515 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2516 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2517 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2518 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));
2519 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2520 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2522 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2523 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2524 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2525 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2526 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2527 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2528 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2529 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2530 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2531 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2532 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2533 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2534 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2535 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2536 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2537 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2538 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2539 if (rsurfacepass == RSURFPASS_BACKGROUND)
2541 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2542 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2543 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2547 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2549 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2550 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2551 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2552 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2553 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2555 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2556 if (rsurface.rtlight)
2558 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2559 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2564 case RENDERPATH_D3D10:
2565 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2567 case RENDERPATH_D3D11:
2568 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2570 case RENDERPATH_GL20:
2571 case RENDERPATH_GLES2:
2572 if (!vid.useinterleavedarrays)
2574 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);
2575 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2576 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2577 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2578 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2579 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2580 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2581 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2585 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);
2586 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2588 R_SetupShader_SetPermutationGLSL(mode, permutation);
2589 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2590 if (mode == SHADERMODE_LIGHTSOURCE)
2592 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2593 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2594 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2595 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2596 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2597 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);
2599 // additive passes are only darkened by fog, not tinted
2600 if (r_glsl_permutation->loc_FogColor >= 0)
2601 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2602 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2606 if (mode == SHADERMODE_FLATCOLOR)
2608 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2610 else if (mode == SHADERMODE_LIGHTDIRECTION)
2612 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]);
2613 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]);
2614 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);
2615 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);
2616 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);
2617 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]);
2618 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]);
2622 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]);
2623 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]);
2624 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);
2625 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);
2626 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);
2628 // additive passes are only darkened by fog, not tinted
2629 if (r_glsl_permutation->loc_FogColor >= 0)
2631 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2632 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2634 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2636 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);
2637 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]);
2638 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]);
2639 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]);
2640 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]);
2641 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2642 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2643 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2644 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]);
2646 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2647 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2648 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2649 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]);
2650 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]);
2652 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2653 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));
2654 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2655 if (r_glsl_permutation->loc_Color_Pants >= 0)
2657 if (rsurface.texture->pantstexture)
2658 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2660 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2662 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2664 if (rsurface.texture->shirttexture)
2665 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2667 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2669 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]);
2670 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2671 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2672 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2673 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));
2674 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]);
2675 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2676 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);}
2677 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2679 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2680 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2681 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2682 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2683 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2684 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2685 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2686 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2687 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2688 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2689 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2690 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2691 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2692 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2693 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);
2694 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2695 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2696 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2697 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2698 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2699 if (rsurfacepass == RSURFPASS_BACKGROUND)
2701 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);
2702 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);
2703 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);
2707 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);
2709 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2710 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2711 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2712 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2713 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2715 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2716 if (rsurface.rtlight)
2718 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2719 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2722 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2725 case RENDERPATH_GL13:
2726 case RENDERPATH_GL11:
2728 case RENDERPATH_SOFT:
2729 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);
2730 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2731 R_SetupShader_SetPermutationSoft(mode, permutation);
2732 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2733 if (mode == SHADERMODE_LIGHTSOURCE)
2735 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2736 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2737 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2738 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2740 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2742 // additive passes are only darkened by fog, not tinted
2743 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2744 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2748 if (mode == SHADERMODE_FLATCOLOR)
2750 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2752 else if (mode == SHADERMODE_LIGHTDIRECTION)
2754 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]);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2756 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);
2757 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);
2758 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2759 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]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2765 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2766 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);
2767 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);
2768 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2770 // additive passes are only darkened by fog, not tinted
2771 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2775 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);
2776 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2777 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2778 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]);
2779 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]);
2780 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2781 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2782 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2783 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2785 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2786 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2787 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2788 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2789 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]);
2791 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2792 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));
2793 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2794 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2796 if (rsurface.texture->pantstexture)
2797 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2799 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2801 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2803 if (rsurface.texture->shirttexture)
2804 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2806 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2808 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2809 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2810 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2811 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2812 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));
2813 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2814 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2816 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2817 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2818 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2819 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2820 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2821 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2822 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2823 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2824 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2825 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2826 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2827 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2828 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2829 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2830 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2831 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2832 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2833 if (rsurfacepass == RSURFPASS_BACKGROUND)
2835 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2836 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2837 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2841 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2843 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2844 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2845 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2846 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2847 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2849 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2850 if (rsurface.rtlight)
2852 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2853 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2860 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2862 // select a permutation of the lighting shader appropriate to this
2863 // combination of texture, entity, light source, and fogging, only use the
2864 // minimum features necessary to avoid wasting rendering time in the
2865 // fragment shader on features that are not being used
2866 unsigned int permutation = 0;
2867 unsigned int mode = 0;
2868 const float *lightcolorbase = rtlight->currentcolor;
2869 float ambientscale = rtlight->ambientscale;
2870 float diffusescale = rtlight->diffusescale;
2871 float specularscale = rtlight->specularscale;
2872 // this is the location of the light in view space
2873 vec3_t viewlightorigin;
2874 // this transforms from view space (camera) to light space (cubemap)
2875 matrix4x4_t viewtolight;
2876 matrix4x4_t lighttoview;
2877 float viewtolight16f[16];
2878 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2880 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2881 if (rtlight->currentcubemap != r_texture_whitecube)
2882 permutation |= SHADERPERMUTATION_CUBEFILTER;
2883 if (diffusescale > 0)
2884 permutation |= SHADERPERMUTATION_DIFFUSE;
2885 if (specularscale > 0)
2886 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2887 if (r_shadow_usingshadowmap2d)
2889 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2890 if (r_shadow_shadowmapvsdct)
2891 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2893 if (r_shadow_shadowmapsampler)
2894 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2895 if (r_shadow_shadowmappcf > 1)
2896 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2897 else if (r_shadow_shadowmappcf)
2898 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2900 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2901 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2902 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2903 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2904 switch(vid.renderpath)
2906 case RENDERPATH_D3D9:
2908 R_SetupShader_SetPermutationHLSL(mode, permutation);
2909 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2910 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2911 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2912 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2913 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2914 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2915 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2916 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2917 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2918 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2920 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2921 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2922 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2923 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2924 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2925 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2928 case RENDERPATH_D3D10:
2929 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2931 case RENDERPATH_D3D11:
2932 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2934 case RENDERPATH_GL20:
2935 case RENDERPATH_GLES2:
2936 R_SetupShader_SetPermutationGLSL(mode, permutation);
2937 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2938 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2939 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);
2940 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);
2941 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);
2942 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]);
2943 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]);
2944 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));
2945 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]);
2946 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2948 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2949 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2950 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2951 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2952 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2953 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2955 case RENDERPATH_GL13:
2956 case RENDERPATH_GL11:
2958 case RENDERPATH_SOFT:
2959 R_SetupShader_SetPermutationGLSL(mode, permutation);
2960 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2961 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2962 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2963 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2964 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2965 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2966 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]);
2967 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));
2968 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2969 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2971 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2972 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2973 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2974 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2975 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2976 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2981 #define SKINFRAME_HASH 1024
2985 int loadsequence; // incremented each level change
2986 memexpandablearray_t array;
2987 skinframe_t *hash[SKINFRAME_HASH];
2990 r_skinframe_t r_skinframe;
2992 void R_SkinFrame_PrepareForPurge(void)
2994 r_skinframe.loadsequence++;
2995 // wrap it without hitting zero
2996 if (r_skinframe.loadsequence >= 200)
2997 r_skinframe.loadsequence = 1;
3000 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3004 // mark the skinframe as used for the purging code
3005 skinframe->loadsequence = r_skinframe.loadsequence;
3008 void R_SkinFrame_Purge(void)
3012 for (i = 0;i < SKINFRAME_HASH;i++)
3014 for (s = r_skinframe.hash[i];s;s = s->next)
3016 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3018 if (s->merged == s->base)
3020 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3021 R_PurgeTexture(s->stain );s->stain = NULL;
3022 R_PurgeTexture(s->merged);s->merged = NULL;
3023 R_PurgeTexture(s->base );s->base = NULL;
3024 R_PurgeTexture(s->pants );s->pants = NULL;
3025 R_PurgeTexture(s->shirt );s->shirt = NULL;
3026 R_PurgeTexture(s->nmap );s->nmap = NULL;
3027 R_PurgeTexture(s->gloss );s->gloss = NULL;
3028 R_PurgeTexture(s->glow );s->glow = NULL;
3029 R_PurgeTexture(s->fog );s->fog = NULL;
3030 R_PurgeTexture(s->reflect);s->reflect = NULL;
3031 s->loadsequence = 0;
3037 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3039 char basename[MAX_QPATH];
3041 Image_StripImageExtension(name, basename, sizeof(basename));
3043 if( last == NULL ) {
3045 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3046 item = r_skinframe.hash[hashindex];
3051 // linearly search through the hash bucket
3052 for( ; item ; item = item->next ) {
3053 if( !strcmp( item->basename, basename ) ) {
3060 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3064 char basename[MAX_QPATH];
3066 Image_StripImageExtension(name, basename, sizeof(basename));
3068 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3069 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3070 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3074 rtexture_t *dyntexture;
3075 // check whether its a dynamic texture
3076 dyntexture = CL_GetDynTexture( basename );
3077 if (!add && !dyntexture)
3079 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3080 memset(item, 0, sizeof(*item));
3081 strlcpy(item->basename, basename, sizeof(item->basename));
3082 item->base = dyntexture; // either NULL or dyntexture handle
3083 item->textureflags = textureflags;
3084 item->comparewidth = comparewidth;
3085 item->compareheight = compareheight;
3086 item->comparecrc = comparecrc;
3087 item->next = r_skinframe.hash[hashindex];
3088 r_skinframe.hash[hashindex] = item;
3090 else if( item->base == NULL )
3092 rtexture_t *dyntexture;
3093 // check whether its a dynamic texture
3094 // 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]
3095 dyntexture = CL_GetDynTexture( basename );
3096 item->base = dyntexture; // either NULL or dyntexture handle
3099 R_SkinFrame_MarkUsed(item);
3103 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3105 unsigned long long avgcolor[5], wsum; \
3113 for(pix = 0; pix < cnt; ++pix) \
3116 for(comp = 0; comp < 3; ++comp) \
3118 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3121 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3123 for(comp = 0; comp < 3; ++comp) \
3124 avgcolor[comp] += getpixel * w; \
3127 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3128 avgcolor[4] += getpixel; \
3130 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3132 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3133 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3134 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3135 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3138 extern cvar_t gl_picmip;
3139 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3142 unsigned char *pixels;
3143 unsigned char *bumppixels;
3144 unsigned char *basepixels = NULL;
3145 int basepixels_width = 0;
3146 int basepixels_height = 0;
3147 skinframe_t *skinframe;
3148 rtexture_t *ddsbase = NULL;
3149 qboolean ddshasalpha = false;
3150 float ddsavgcolor[4];
3151 char basename[MAX_QPATH];
3152 int miplevel = R_PicmipForFlags(textureflags);
3153 int savemiplevel = miplevel;
3156 if (cls.state == ca_dedicated)
3159 // return an existing skinframe if already loaded
3160 // if loading of the first image fails, don't make a new skinframe as it
3161 // would cause all future lookups of this to be missing
3162 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3163 if (skinframe && skinframe->base)
3166 Image_StripImageExtension(name, basename, sizeof(basename));
3168 // check for DDS texture file first
3169 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3171 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3172 if (basepixels == NULL)
3176 // FIXME handle miplevel
3178 if (developer_loading.integer)
3179 Con_Printf("loading skin \"%s\"\n", name);
3181 // we've got some pixels to store, so really allocate this new texture now
3183 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3184 skinframe->stain = NULL;
3185 skinframe->merged = NULL;
3186 skinframe->base = NULL;
3187 skinframe->pants = NULL;
3188 skinframe->shirt = NULL;
3189 skinframe->nmap = NULL;
3190 skinframe->gloss = NULL;
3191 skinframe->glow = NULL;
3192 skinframe->fog = NULL;
3193 skinframe->reflect = NULL;
3194 skinframe->hasalpha = false;
3198 skinframe->base = ddsbase;
3199 skinframe->hasalpha = ddshasalpha;
3200 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3201 if (r_loadfog && skinframe->hasalpha)
3202 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3203 //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]);
3207 basepixels_width = image_width;
3208 basepixels_height = image_height;
3209 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);
3210 if (textureflags & TEXF_ALPHA)
3212 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3214 if (basepixels[j] < 255)
3216 skinframe->hasalpha = true;
3220 if (r_loadfog && skinframe->hasalpha)
3222 // has transparent pixels
3223 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3224 for (j = 0;j < image_width * image_height * 4;j += 4)
3229 pixels[j+3] = basepixels[j+3];
3231 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);
3235 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3236 //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]);
3237 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3238 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3239 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3240 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3245 mymiplevel = savemiplevel;
3246 if (r_loadnormalmap)
3247 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);
3248 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3250 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3251 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3252 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3253 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3256 // _norm is the name used by tenebrae and has been adopted as standard
3257 if (r_loadnormalmap && skinframe->nmap == NULL)
3259 mymiplevel = savemiplevel;
3260 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3262 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);
3266 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3268 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3269 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3270 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);
3272 Mem_Free(bumppixels);
3274 else if (r_shadow_bumpscale_basetexture.value > 0)
3276 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3277 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3278 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);
3281 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3282 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3285 // _luma is supported only for tenebrae compatibility
3286 // _glow is the preferred name
3287 mymiplevel = savemiplevel;
3288 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))))
3290 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);
3291 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3292 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3293 Mem_Free(pixels);pixels = NULL;
3296 mymiplevel = savemiplevel;
3297 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3299 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);
3300 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3301 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3306 mymiplevel = savemiplevel;
3307 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3309 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);
3310 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3311 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3316 mymiplevel = savemiplevel;
3317 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3319 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);
3320 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3321 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3326 mymiplevel = savemiplevel;
3327 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3329 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);
3330 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3331 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3337 Mem_Free(basepixels);
3342 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3343 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3346 unsigned char *temp1, *temp2;
3347 skinframe_t *skinframe;
3349 if (cls.state == ca_dedicated)
3352 // if already loaded just return it, otherwise make a new skinframe
3353 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3354 if (skinframe && skinframe->base)
3357 skinframe->stain = NULL;
3358 skinframe->merged = NULL;
3359 skinframe->base = NULL;
3360 skinframe->pants = NULL;
3361 skinframe->shirt = NULL;
3362 skinframe->nmap = NULL;
3363 skinframe->gloss = NULL;
3364 skinframe->glow = NULL;
3365 skinframe->fog = NULL;
3366 skinframe->reflect = NULL;
3367 skinframe->hasalpha = false;
3369 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3373 if (developer_loading.integer)
3374 Con_Printf("loading 32bit skin \"%s\"\n", name);
3376 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3378 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3379 temp2 = temp1 + width * height * 4;
3380 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3381 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);
3384 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3385 if (textureflags & TEXF_ALPHA)
3387 for (i = 3;i < width * height * 4;i += 4)
3389 if (skindata[i] < 255)
3391 skinframe->hasalpha = true;
3395 if (r_loadfog && skinframe->hasalpha)
3397 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3398 memcpy(fogpixels, skindata, width * height * 4);
3399 for (i = 0;i < width * height * 4;i += 4)
3400 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3401 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3402 Mem_Free(fogpixels);
3406 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3407 //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]);
3412 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3416 skinframe_t *skinframe;
3418 if (cls.state == ca_dedicated)
3421 // if already loaded just return it, otherwise make a new skinframe
3422 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3423 if (skinframe && skinframe->base)
3426 skinframe->stain = NULL;
3427 skinframe->merged = NULL;
3428 skinframe->base = NULL;
3429 skinframe->pants = NULL;
3430 skinframe->shirt = NULL;
3431 skinframe->nmap = NULL;
3432 skinframe->gloss = NULL;
3433 skinframe->glow = NULL;
3434 skinframe->fog = NULL;
3435 skinframe->reflect = NULL;
3436 skinframe->hasalpha = false;
3438 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3442 if (developer_loading.integer)
3443 Con_Printf("loading quake skin \"%s\"\n", name);
3445 // 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)
3446 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3447 memcpy(skinframe->qpixels, skindata, width*height);
3448 skinframe->qwidth = width;
3449 skinframe->qheight = height;
3452 for (i = 0;i < width * height;i++)
3453 featuresmask |= palette_featureflags[skindata[i]];
3455 skinframe->hasalpha = false;
3456 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3457 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3458 skinframe->qgeneratemerged = true;
3459 skinframe->qgeneratebase = skinframe->qhascolormapping;
3460 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3462 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3463 //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]);
3468 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3472 unsigned char *skindata;
3474 if (!skinframe->qpixels)
3477 if (!skinframe->qhascolormapping)
3478 colormapped = false;
3482 if (!skinframe->qgeneratebase)
3487 if (!skinframe->qgeneratemerged)
3491 width = skinframe->qwidth;
3492 height = skinframe->qheight;
3493 skindata = skinframe->qpixels;
3495 if (skinframe->qgeneratenmap)
3497 unsigned char *temp1, *temp2;
3498 skinframe->qgeneratenmap = false;
3499 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3500 temp2 = temp1 + width * height * 4;
3501 // use either a custom palette or the quake palette
3502 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3503 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3504 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);
3508 if (skinframe->qgenerateglow)
3510 skinframe->qgenerateglow = false;
3511 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3516 skinframe->qgeneratebase = false;
3517 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);
3518 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3519 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3523 skinframe->qgeneratemerged = false;
3524 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);
3527 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3529 Mem_Free(skinframe->qpixels);
3530 skinframe->qpixels = NULL;
3534 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)
3537 skinframe_t *skinframe;
3539 if (cls.state == ca_dedicated)
3542 // if already loaded just return it, otherwise make a new skinframe
3543 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3544 if (skinframe && skinframe->base)
3547 skinframe->stain = NULL;
3548 skinframe->merged = NULL;
3549 skinframe->base = NULL;
3550 skinframe->pants = NULL;
3551 skinframe->shirt = NULL;
3552 skinframe->nmap = NULL;
3553 skinframe->gloss = NULL;
3554 skinframe->glow = NULL;
3555 skinframe->fog = NULL;
3556 skinframe->reflect = NULL;
3557 skinframe->hasalpha = false;
3559 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3563 if (developer_loading.integer)
3564 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3566 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3567 if (textureflags & TEXF_ALPHA)
3569 for (i = 0;i < width * height;i++)
3571 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3573 skinframe->hasalpha = true;
3577 if (r_loadfog && skinframe->hasalpha)
3578 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3581 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3582 //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]);
3587 skinframe_t *R_SkinFrame_LoadMissing(void)
3589 skinframe_t *skinframe;
3591 if (cls.state == ca_dedicated)
3594 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3595 skinframe->stain = NULL;
3596 skinframe->merged = NULL;
3597 skinframe->base = NULL;
3598 skinframe->pants = NULL;
3599 skinframe->shirt = NULL;
3600 skinframe->nmap = NULL;
3601 skinframe->gloss = NULL;
3602 skinframe->glow = NULL;
3603 skinframe->fog = NULL;
3604 skinframe->reflect = NULL;
3605 skinframe->hasalpha = false;
3607 skinframe->avgcolor[0] = rand() / RAND_MAX;
3608 skinframe->avgcolor[1] = rand() / RAND_MAX;
3609 skinframe->avgcolor[2] = rand() / RAND_MAX;
3610 skinframe->avgcolor[3] = 1;
3615 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3616 typedef struct suffixinfo_s
3619 qboolean flipx, flipy, flipdiagonal;
3622 static suffixinfo_t suffix[3][6] =
3625 {"px", false, false, false},
3626 {"nx", false, false, false},
3627 {"py", false, false, false},
3628 {"ny", false, false, false},
3629 {"pz", false, false, false},
3630 {"nz", false, false, false}
3633 {"posx", false, false, false},
3634 {"negx", false, false, false},
3635 {"posy", false, false, false},
3636 {"negy", false, false, false},
3637 {"posz", false, false, false},
3638 {"negz", false, false, false}
3641 {"rt", true, false, true},
3642 {"lf", false, true, true},
3643 {"ft", true, true, false},
3644 {"bk", false, false, false},
3645 {"up", true, false, true},
3646 {"dn", true, false, true}
3650 static int componentorder[4] = {0, 1, 2, 3};
3652 rtexture_t *R_LoadCubemap(const char *basename)
3654 int i, j, cubemapsize;
3655 unsigned char *cubemappixels, *image_buffer;
3656 rtexture_t *cubemaptexture;
3658 // must start 0 so the first loadimagepixels has no requested width/height
3660 cubemappixels = NULL;
3661 cubemaptexture = NULL;
3662 // keep trying different suffix groups (posx, px, rt) until one loads
3663 for (j = 0;j < 3 && !cubemappixels;j++)
3665 // load the 6 images in the suffix group
3666 for (i = 0;i < 6;i++)
3668 // generate an image name based on the base and and suffix
3669 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3671 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3673 // an image loaded, make sure width and height are equal
3674 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3676 // if this is the first image to load successfully, allocate the cubemap memory
3677 if (!cubemappixels && image_width >= 1)
3679 cubemapsize = image_width;
3680 // note this clears to black, so unavailable sides are black
3681 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3683 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3685 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);
3688 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3690 Mem_Free(image_buffer);
3694 // if a cubemap loaded, upload it
3697 if (developer_loading.integer)
3698 Con_Printf("loading cubemap \"%s\"\n", basename);
3700 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3701 Mem_Free(cubemappixels);
3705 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3706 if (developer_loading.integer)
3708 Con_Printf("(tried tried images ");
3709 for (j = 0;j < 3;j++)
3710 for (i = 0;i < 6;i++)
3711 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3712 Con_Print(" and was unable to find any of them).\n");
3715 return cubemaptexture;
3718 rtexture_t *R_GetCubemap(const char *basename)
3721 for (i = 0;i < r_texture_numcubemaps;i++)
3722 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3723 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3724 if (i >= MAX_CUBEMAPS)
3725 return r_texture_whitecube;
3726 r_texture_numcubemaps++;
3727 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3728 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3729 return r_texture_cubemaps[i].texture;
3732 void R_FreeCubemaps(void)
3735 for (i = 0;i < r_texture_numcubemaps;i++)
3737 if (developer_loading.integer)
3738 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3739 if (r_texture_cubemaps[i].texture)
3740 R_FreeTexture(r_texture_cubemaps[i].texture);
3742 r_texture_numcubemaps = 0;
3745 void R_Main_FreeViewCache(void)
3747 if (r_refdef.viewcache.entityvisible)
3748 Mem_Free(r_refdef.viewcache.entityvisible);
3749 if (r_refdef.viewcache.world_pvsbits)
3750 Mem_Free(r_refdef.viewcache.world_pvsbits);
3751 if (r_refdef.viewcache.world_leafvisible)
3752 Mem_Free(r_refdef.viewcache.world_leafvisible);
3753 if (r_refdef.viewcache.world_surfacevisible)
3754 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3755 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3758 void R_Main_ResizeViewCache(void)
3760 int numentities = r_refdef.scene.numentities;
3761 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3762 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3763 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3764 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3765 if (r_refdef.viewcache.maxentities < numentities)
3767 r_refdef.viewcache.maxentities = numentities;
3768 if (r_refdef.viewcache.entityvisible)
3769 Mem_Free(r_refdef.viewcache.entityvisible);
3770 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3772 if (r_refdef.viewcache.world_numclusters != numclusters)
3774 r_refdef.viewcache.world_numclusters = numclusters;
3775 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3776 if (r_refdef.viewcache.world_pvsbits)
3777 Mem_Free(r_refdef.viewcache.world_pvsbits);
3778 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3780 if (r_refdef.viewcache.world_numleafs != numleafs)
3782 r_refdef.viewcache.world_numleafs = numleafs;
3783 if (r_refdef.viewcache.world_leafvisible)
3784 Mem_Free(r_refdef.viewcache.world_leafvisible);
3785 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3787 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3789 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3790 if (r_refdef.viewcache.world_surfacevisible)
3791 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3792 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3796 extern rtexture_t *loadingscreentexture;
3797 void gl_main_start(void)
3799 loadingscreentexture = NULL;
3800 r_texture_blanknormalmap = NULL;
3801 r_texture_white = NULL;
3802 r_texture_grey128 = NULL;
3803 r_texture_black = NULL;
3804 r_texture_whitecube = NULL;
3805 r_texture_normalizationcube = NULL;
3806 r_texture_fogattenuation = NULL;
3807 r_texture_fogheighttexture = NULL;
3808 r_texture_gammaramps = NULL;
3809 r_texture_numcubemaps = 0;
3811 r_loaddds = r_texture_dds_load.integer != 0;
3812 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3814 switch(vid.renderpath)
3816 case RENDERPATH_GL20:
3817 case RENDERPATH_D3D9:
3818 case RENDERPATH_D3D10:
3819 case RENDERPATH_D3D11:
3820 case RENDERPATH_SOFT:
3821 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3822 Cvar_SetValueQuick(&gl_combine, 1);
3823 Cvar_SetValueQuick(&r_glsl, 1);
3824 r_loadnormalmap = true;
3828 case RENDERPATH_GL13:
3829 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3830 Cvar_SetValueQuick(&gl_combine, 1);
3831 Cvar_SetValueQuick(&r_glsl, 0);
3832 r_loadnormalmap = false;
3833 r_loadgloss = false;
3836 case RENDERPATH_GL11:
3837 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3838 Cvar_SetValueQuick(&gl_combine, 0);
3839 Cvar_SetValueQuick(&r_glsl, 0);
3840 r_loadnormalmap = false;
3841 r_loadgloss = false;
3844 case RENDERPATH_GLES2:
3845 Cvar_SetValueQuick(&r_textureunits, 1);
3846 Cvar_SetValueQuick(&gl_combine, 1);
3847 Cvar_SetValueQuick(&r_glsl, 1);
3848 r_loadnormalmap = true;
3849 r_loadgloss = false;
3855 R_FrameData_Reset();
3859 memset(r_queries, 0, sizeof(r_queries));
3861 r_qwskincache = NULL;
3862 r_qwskincache_size = 0;
3864 // due to caching of texture_t references, the collision cache must be reset
3865 Collision_Cache_Reset(true);
3867 // set up r_skinframe loading system for textures
3868 memset(&r_skinframe, 0, sizeof(r_skinframe));
3869 r_skinframe.loadsequence = 1;
3870 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3872 r_main_texturepool = R_AllocTexturePool();
3873 R_BuildBlankTextures();
3875 if (vid.support.arb_texture_cube_map)
3878 R_BuildNormalizationCube();
3880 r_texture_fogattenuation = NULL;
3881 r_texture_fogheighttexture = NULL;
3882 r_texture_gammaramps = NULL;
3883 //r_texture_fogintensity = NULL;
3884 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3885 memset(&r_waterstate, 0, sizeof(r_waterstate));
3886 r_glsl_permutation = NULL;
3887 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3888 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3889 glslshaderstring = NULL;
3891 r_hlsl_permutation = NULL;
3892 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3893 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3895 hlslshaderstring = NULL;
3896 memset(&r_svbsp, 0, sizeof (r_svbsp));
3898 r_refdef.fogmasktable_density = 0;
3901 void gl_main_shutdown(void)
3904 R_FrameData_Reset();
3906 R_Main_FreeViewCache();
3908 switch(vid.renderpath)
3910 case RENDERPATH_GL11:
3911 case RENDERPATH_GL13:
3912 case RENDERPATH_GL20:
3913 case RENDERPATH_GLES2:
3915 qglDeleteQueriesARB(r_maxqueries, r_queries);
3917 case RENDERPATH_D3D9:
3918 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3920 case RENDERPATH_D3D10:
3921 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3923 case RENDERPATH_D3D11:
3924 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3926 case RENDERPATH_SOFT:
3932 memset(r_queries, 0, sizeof(r_queries));
3934 r_qwskincache = NULL;
3935 r_qwskincache_size = 0;
3937 // clear out the r_skinframe state
3938 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3939 memset(&r_skinframe, 0, sizeof(r_skinframe));
3942 Mem_Free(r_svbsp.nodes);
3943 memset(&r_svbsp, 0, sizeof (r_svbsp));
3944 R_FreeTexturePool(&r_main_texturepool);
3945 loadingscreentexture = NULL;
3946 r_texture_blanknormalmap = NULL;
3947 r_texture_white = NULL;
3948 r_texture_grey128 = NULL;
3949 r_texture_black = NULL;
3950 r_texture_whitecube = NULL;
3951 r_texture_normalizationcube = NULL;
3952 r_texture_fogattenuation = NULL;
3953 r_texture_fogheighttexture = NULL;
3954 r_texture_gammaramps = NULL;
3955 r_texture_numcubemaps = 0;
3956 //r_texture_fogintensity = NULL;
3957 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3958 memset(&r_waterstate, 0, sizeof(r_waterstate));
3961 r_glsl_permutation = NULL;
3962 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3963 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3964 glslshaderstring = NULL;
3966 r_hlsl_permutation = NULL;
3967 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3968 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3970 hlslshaderstring = NULL;
3973 extern void CL_ParseEntityLump(char *entitystring);
3974 void gl_main_newmap(void)
3976 // FIXME: move this code to client
3977 char *entities, entname[MAX_QPATH];
3979 Mem_Free(r_qwskincache);
3980 r_qwskincache = NULL;
3981 r_qwskincache_size = 0;
3984 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3985 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3987 CL_ParseEntityLump(entities);
3991 if (cl.worldmodel->brush.entities)
3992 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3994 R_Main_FreeViewCache();
3996 R_FrameData_Reset();
3999 void GL_Main_Init(void)
4001 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4003 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4004 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4005 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4006 if (gamemode == GAME_NEHAHRA)
4008 Cvar_RegisterVariable (&gl_fogenable);
4009 Cvar_RegisterVariable (&gl_fogdensity);
4010 Cvar_RegisterVariable (&gl_fogred);
4011 Cvar_RegisterVariable (&gl_foggreen);
4012 Cvar_RegisterVariable (&gl_fogblue);
4013 Cvar_RegisterVariable (&gl_fogstart);
4014 Cvar_RegisterVariable (&gl_fogend);
4015 Cvar_RegisterVariable (&gl_skyclip);
4017 Cvar_RegisterVariable(&r_motionblur);
4018 Cvar_RegisterVariable(&r_motionblur_maxblur);
4019 Cvar_RegisterVariable(&r_motionblur_bmin);
4020 Cvar_RegisterVariable(&r_motionblur_vmin);
4021 Cvar_RegisterVariable(&r_motionblur_vmax);
4022 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4023 Cvar_RegisterVariable(&r_motionblur_randomize);
4024 Cvar_RegisterVariable(&r_damageblur);
4025 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4026 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4027 Cvar_RegisterVariable(&r_equalize_entities_by);
4028 Cvar_RegisterVariable(&r_equalize_entities_to);
4029 Cvar_RegisterVariable(&r_depthfirst);
4030 Cvar_RegisterVariable(&r_useinfinitefarclip);
4031 Cvar_RegisterVariable(&r_farclip_base);
4032 Cvar_RegisterVariable(&r_farclip_world);
4033 Cvar_RegisterVariable(&r_nearclip);
4034 Cvar_RegisterVariable(&r_showbboxes);
4035 Cvar_RegisterVariable(&r_showsurfaces);
4036 Cvar_RegisterVariable(&r_showtris);
4037 Cvar_RegisterVariable(&r_shownormals);
4038 Cvar_RegisterVariable(&r_showlighting);
4039 Cvar_RegisterVariable(&r_showshadowvolumes);
4040 Cvar_RegisterVariable(&r_showcollisionbrushes);
4041 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4042 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4043 Cvar_RegisterVariable(&r_showdisabledepthtest);
4044 Cvar_RegisterVariable(&r_drawportals);
4045 Cvar_RegisterVariable(&r_drawentities);
4046 Cvar_RegisterVariable(&r_draw2d);
4047 Cvar_RegisterVariable(&r_drawworld);
4048 Cvar_RegisterVariable(&r_cullentities_trace);
4049 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4050 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4051 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4052 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4053 Cvar_RegisterVariable(&r_drawviewmodel);
4054 Cvar_RegisterVariable(&r_drawexteriormodel);
4055 Cvar_RegisterVariable(&r_speeds);
4056 Cvar_RegisterVariable(&r_fullbrights);
4057 Cvar_RegisterVariable(&r_wateralpha);
4058 Cvar_RegisterVariable(&r_dynamic);
4059 Cvar_RegisterVariable(&r_fakelight);
4060 Cvar_RegisterVariable(&r_fakelight_intensity);
4061 Cvar_RegisterVariable(&r_fullbright);
4062 Cvar_RegisterVariable(&r_shadows);
4063 Cvar_RegisterVariable(&r_shadows_darken);
4064 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4065 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4066 Cvar_RegisterVariable(&r_shadows_throwdistance);
4067 Cvar_RegisterVariable(&r_shadows_throwdirection);
4068 Cvar_RegisterVariable(&r_shadows_focus);
4069 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4070 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4071 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4072 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4073 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4074 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4075 Cvar_RegisterVariable(&r_fog_exp2);
4076 Cvar_RegisterVariable(&r_fog_clear);
4077 Cvar_RegisterVariable(&r_drawfog);
4078 Cvar_RegisterVariable(&r_transparentdepthmasking);
4079 Cvar_RegisterVariable(&r_texture_dds_load);
4080 Cvar_RegisterVariable(&r_texture_dds_save);
4081 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4082 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4083 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4084 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4085 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4086 Cvar_RegisterVariable(&r_textureunits);
4087 Cvar_RegisterVariable(&gl_combine);
4088 Cvar_RegisterVariable(&r_glsl);
4089 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4090 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4091 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4092 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4093 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4094 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4095 Cvar_RegisterVariable(&r_glsl_postprocess);
4096 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4097 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4098 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4099 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4100 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4101 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4102 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4103 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4105 Cvar_RegisterVariable(&r_water);
4106 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4107 Cvar_RegisterVariable(&r_water_clippingplanebias);
4108 Cvar_RegisterVariable(&r_water_refractdistort);
4109 Cvar_RegisterVariable(&r_water_reflectdistort);
4110 Cvar_RegisterVariable(&r_water_scissormode);
4111 Cvar_RegisterVariable(&r_lerpsprites);
4112 Cvar_RegisterVariable(&r_lerpmodels);
4113 Cvar_RegisterVariable(&r_lerplightstyles);
4114 Cvar_RegisterVariable(&r_waterscroll);
4115 Cvar_RegisterVariable(&r_bloom);
4116 Cvar_RegisterVariable(&r_bloom_colorscale);
4117 Cvar_RegisterVariable(&r_bloom_brighten);
4118 Cvar_RegisterVariable(&r_bloom_blur);
4119 Cvar_RegisterVariable(&r_bloom_resolution);
4120 Cvar_RegisterVariable(&r_bloom_colorexponent);
4121 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4122 Cvar_RegisterVariable(&r_hdr);
4123 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4124 Cvar_RegisterVariable(&r_hdr_glowintensity);
4125 Cvar_RegisterVariable(&r_hdr_range);
4126 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4127 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4128 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4129 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4130 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4131 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4132 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4133 Cvar_RegisterVariable(&developer_texturelogging);
4134 Cvar_RegisterVariable(&gl_lightmaps);
4135 Cvar_RegisterVariable(&r_test);
4136 Cvar_RegisterVariable(&r_glsl_saturation);
4137 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4138 Cvar_RegisterVariable(&r_framedatasize);
4139 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4140 Cvar_SetValue("r_fullbrights", 0);
4141 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4143 Cvar_RegisterVariable(&r_track_sprites);
4144 Cvar_RegisterVariable(&r_track_sprites_flags);
4145 Cvar_RegisterVariable(&r_track_sprites_scalew);
4146 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4147 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4148 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4149 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4150 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4153 extern void R_Textures_Init(void);
4154 extern void GL_Draw_Init(void);
4155 extern void GL_Main_Init(void);
4156 extern void R_Shadow_Init(void);
4157 extern void R_Sky_Init(void);
4158 extern void GL_Surf_Init(void);
4159 extern void R_Particles_Init(void);
4160 extern void R_Explosion_Init(void);
4161 extern void gl_backend_init(void);
4162 extern void Sbar_Init(void);
4163 extern void R_LightningBeams_Init(void);
4164 extern void Mod_RenderInit(void);
4165 extern void Font_Init(void);
4167 void Render_Init(void)
4180 R_LightningBeams_Init();
4189 extern char *ENGINE_EXTENSIONS;
4192 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4193 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4194 gl_version = (const char *)qglGetString(GL_VERSION);
4195 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4199 if (!gl_platformextensions)
4200 gl_platformextensions = "";
4202 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4203 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4204 Con_Printf("GL_VERSION: %s\n", gl_version);
4205 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4206 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4208 VID_CheckExtensions();
4210 // LordHavoc: report supported extensions
4211 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4213 // clear to black (loading plaque will be seen over this)
4214 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4217 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4221 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4223 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4226 p = r_refdef.view.frustum + i;
4231 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4235 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4239 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4243 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4247 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4251 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4255 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4259 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4267 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4271 for (i = 0;i < numplanes;i++)
4278 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4282 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4286 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4290 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4294 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4298 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4302 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4306 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4314 //==================================================================================
4316 // LordHavoc: this stores temporary data used within the same frame
4318 typedef struct r_framedata_mem_s
4320 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4321 size_t size; // how much usable space
4322 size_t current; // how much space in use
4323 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4324 size_t wantedsize; // how much space was allocated
4325 unsigned char *data; // start of real data (16byte aligned)
4329 static r_framedata_mem_t *r_framedata_mem;
4331 void R_FrameData_Reset(void)
4333 while (r_framedata_mem)
4335 r_framedata_mem_t *next = r_framedata_mem->purge;
4336 Mem_Free(r_framedata_mem);
4337 r_framedata_mem = next;
4341 void R_FrameData_Resize(void)
4344 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4345 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4346 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4348 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4349 newmem->wantedsize = wantedsize;
4350 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4351 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4352 newmem->current = 0;
4354 newmem->purge = r_framedata_mem;
4355 r_framedata_mem = newmem;
4359 void R_FrameData_NewFrame(void)
4361 R_FrameData_Resize();
4362 if (!r_framedata_mem)
4364 // if we ran out of space on the last frame, free the old memory now
4365 while (r_framedata_mem->purge)
4367 // repeatedly remove the second item in the list, leaving only head
4368 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4369 Mem_Free(r_framedata_mem->purge);
4370 r_framedata_mem->purge = next;
4372 // reset the current mem pointer
4373 r_framedata_mem->current = 0;
4374 r_framedata_mem->mark = 0;
4377 void *R_FrameData_Alloc(size_t size)
4381 // align to 16 byte boundary - the data pointer is already aligned, so we
4382 // only need to ensure the size of every allocation is also aligned
4383 size = (size + 15) & ~15;
4385 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4387 // emergency - we ran out of space, allocate more memory
4388 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4389 R_FrameData_Resize();
4392 data = r_framedata_mem->data + r_framedata_mem->current;
4393 r_framedata_mem->current += size;
4395 // count the usage for stats
4396 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4397 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4399 return (void *)data;
4402 void *R_FrameData_Store(size_t size, void *data)
4404 void *d = R_FrameData_Alloc(size);
4406 memcpy(d, data, size);
4410 void R_FrameData_SetMark(void)
4412 if (!r_framedata_mem)
4414 r_framedata_mem->mark = r_framedata_mem->current;
4417 void R_FrameData_ReturnToMark(void)
4419 if (!r_framedata_mem)
4421 r_framedata_mem->current = r_framedata_mem->mark;
4424 //==================================================================================
4426 // LordHavoc: animcache originally written by Echon, rewritten since then
4429 * Animation cache prevents re-generating mesh data for an animated model
4430 * multiple times in one frame for lighting, shadowing, reflections, etc.
4433 void R_AnimCache_Free(void)
4437 void R_AnimCache_ClearCache(void)
4440 entity_render_t *ent;
4442 for (i = 0;i < r_refdef.scene.numentities;i++)
4444 ent = r_refdef.scene.entities[i];
4445 ent->animcache_vertex3f = NULL;
4446 ent->animcache_normal3f = NULL;
4447 ent->animcache_svector3f = NULL;
4448 ent->animcache_tvector3f = NULL;
4449 ent->animcache_vertexmesh = NULL;
4450 ent->animcache_vertex3fbuffer = NULL;
4451 ent->animcache_vertexmeshbuffer = NULL;
4455 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4459 // check if we need the meshbuffers
4460 if (!vid.useinterleavedarrays)
4463 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4464 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4465 // TODO: upload vertex3f buffer?
4466 if (ent->animcache_vertexmesh)
4468 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4469 for (i = 0;i < numvertices;i++)
4470 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4471 if (ent->animcache_svector3f)
4472 for (i = 0;i < numvertices;i++)
4473 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4474 if (ent->animcache_tvector3f)
4475 for (i = 0;i < numvertices;i++)
4476 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4477 if (ent->animcache_normal3f)
4478 for (i = 0;i < numvertices;i++)
4479 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4480 // TODO: upload vertexmeshbuffer?
4484 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4486 dp_model_t *model = ent->model;
4488 // see if it's already cached this frame
4489 if (ent->animcache_vertex3f)
4491 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4492 if (wantnormals || wanttangents)
4494 if (ent->animcache_normal3f)
4495 wantnormals = false;
4496 if (ent->animcache_svector3f)
4497 wanttangents = false;
4498 if (wantnormals || wanttangents)
4500 numvertices = model->surfmesh.num_vertices;
4502 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4505 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4506 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4508 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4509 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4515 // see if this ent is worth caching
4516 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4518 // get some memory for this entity and generate mesh data
4519 numvertices = model->surfmesh.num_vertices;
4520 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4522 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4525 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4526 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4528 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4529 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4534 void R_AnimCache_CacheVisibleEntities(void)
4537 qboolean wantnormals = true;
4538 qboolean wanttangents = !r_showsurfaces.integer;
4540 switch(vid.renderpath)
4542 case RENDERPATH_GL20:
4543 case RENDERPATH_D3D9:
4544 case RENDERPATH_D3D10:
4545 case RENDERPATH_D3D11:
4546 case RENDERPATH_GLES2:
4548 case RENDERPATH_GL13:
4549 case RENDERPATH_GL11:
4550 wanttangents = false;
4552 case RENDERPATH_SOFT:
4556 if (r_shownormals.integer)
4557 wanttangents = wantnormals = true;
4559 // TODO: thread this
4560 // NOTE: R_PrepareRTLights() also caches entities
4562 for (i = 0;i < r_refdef.scene.numentities;i++)
4563 if (r_refdef.viewcache.entityvisible[i])
4564 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4567 //==================================================================================
4569 static void R_View_UpdateEntityLighting (void)
4572 entity_render_t *ent;
4573 vec3_t tempdiffusenormal, avg;
4574 vec_t f, fa, fd, fdd;
4575 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4577 for (i = 0;i < r_refdef.scene.numentities;i++)
4579 ent = r_refdef.scene.entities[i];
4581 // skip unseen models
4582 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4586 if (ent->model && ent->model->brush.num_leafs)
4588 // TODO: use modellight for r_ambient settings on world?
4589 VectorSet(ent->modellight_ambient, 0, 0, 0);
4590 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4591 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4595 // fetch the lighting from the worldmodel data
4596 VectorClear(ent->modellight_ambient);
4597 VectorClear(ent->modellight_diffuse);
4598 VectorClear(tempdiffusenormal);
4599 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4602 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4604 // complete lightning for lit sprites
4605 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4606 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4608 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4609 org[2] = org[2] + r_overheadsprites_pushback.value;
4610 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4613 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4615 if(ent->flags & RENDER_EQUALIZE)
4617 // first fix up ambient lighting...
4618 if(r_equalize_entities_minambient.value > 0)
4620 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4623 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4624 if(fa < r_equalize_entities_minambient.value * fd)
4627 // fa'/fd' = minambient
4628 // fa'+0.25*fd' = fa+0.25*fd
4630 // fa' = fd' * minambient
4631 // fd'*(0.25+minambient) = fa+0.25*fd
4633 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4634 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4636 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4637 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
4638 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4639 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4644 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4646 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4647 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4651 // adjust brightness and saturation to target
4652 avg[0] = avg[1] = avg[2] = fa / f;
4653 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4654 avg[0] = avg[1] = avg[2] = fd / f;
4655 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4661 VectorSet(ent->modellight_ambient, 1, 1, 1);
4663 // move the light direction into modelspace coordinates for lighting code
4664 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4665 if(VectorLength2(ent->modellight_lightdir) == 0)
4666 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4667 VectorNormalize(ent->modellight_lightdir);
4671 #define MAX_LINEOFSIGHTTRACES 64
4673 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4676 vec3_t boxmins, boxmaxs;
4679 dp_model_t *model = r_refdef.scene.worldmodel;
4681 if (!model || !model->brush.TraceLineOfSight)
4684 // expand the box a little
4685 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4686 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4687 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4688 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4689 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4690 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4692 // return true if eye is inside enlarged box
4693 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4697 VectorCopy(eye, start);
4698 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4699 if (model->brush.TraceLineOfSight(model, start, end))
4702 // try various random positions
4703 for (i = 0;i < numsamples;i++)
4705 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4706 if (model->brush.TraceLineOfSight(model, start, end))
4714 static void R_View_UpdateEntityVisible (void)
4719 entity_render_t *ent;
4721 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4722 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4723 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4724 : RENDER_EXTERIORMODEL;
4725 if (!r_drawviewmodel.integer)
4726 renderimask |= RENDER_VIEWMODEL;
4727 if (!r_drawexteriormodel.integer)
4728 renderimask |= RENDER_EXTERIORMODEL;
4729 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4731 // worldmodel can check visibility
4732 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4733 for (i = 0;i < r_refdef.scene.numentities;i++)
4735 ent = r_refdef.scene.entities[i];
4736 if (!(ent->flags & renderimask))
4737 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)))
4738 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))
4739 r_refdef.viewcache.entityvisible[i] = true;
4741 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4742 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4744 for (i = 0;i < r_refdef.scene.numentities;i++)
4746 ent = r_refdef.scene.entities[i];
4747 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4749 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4751 continue; // temp entities do pvs only
4752 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4753 ent->last_trace_visibility = realtime;
4754 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4755 r_refdef.viewcache.entityvisible[i] = 0;
4762 // no worldmodel or it can't check visibility
4763 for (i = 0;i < r_refdef.scene.numentities;i++)
4765 ent = r_refdef.scene.entities[i];
4766 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));
4771 /// only used if skyrendermasked, and normally returns false
4772 int R_DrawBrushModelsSky (void)
4775 entity_render_t *ent;
4778 for (i = 0;i < r_refdef.scene.numentities;i++)
4780 if (!r_refdef.viewcache.entityvisible[i])
4782 ent = r_refdef.scene.entities[i];
4783 if (!ent->model || !ent->model->DrawSky)
4785 ent->model->DrawSky(ent);
4791 static void R_DrawNoModel(entity_render_t *ent);
4792 static void R_DrawModels(void)
4795 entity_render_t *ent;
4797 for (i = 0;i < r_refdef.scene.numentities;i++)
4799 if (!r_refdef.viewcache.entityvisible[i])
4801 ent = r_refdef.scene.entities[i];
4802 r_refdef.stats.entities++;
4803 if (ent->model && ent->model->Draw != NULL)
4804 ent->model->Draw(ent);
4810 static void R_DrawModelsDepth(void)
4813 entity_render_t *ent;
4815 for (i = 0;i < r_refdef.scene.numentities;i++)
4817 if (!r_refdef.viewcache.entityvisible[i])
4819 ent = r_refdef.scene.entities[i];
4820 if (ent->model && ent->model->DrawDepth != NULL)
4821 ent->model->DrawDepth(ent);
4825 static void R_DrawModelsDebug(void)
4828 entity_render_t *ent;
4830 for (i = 0;i < r_refdef.scene.numentities;i++)
4832 if (!r_refdef.viewcache.entityvisible[i])
4834 ent = r_refdef.scene.entities[i];
4835 if (ent->model && ent->model->DrawDebug != NULL)
4836 ent->model->DrawDebug(ent);
4840 static void R_DrawModelsAddWaterPlanes(void)
4843 entity_render_t *ent;
4845 for (i = 0;i < r_refdef.scene.numentities;i++)
4847 if (!r_refdef.viewcache.entityvisible[i])
4849 ent = r_refdef.scene.entities[i];
4850 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4851 ent->model->DrawAddWaterPlanes(ent);
4855 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4857 if (r_hdr_irisadaptation.integer)
4861 vec3_t diffusenormal;
4866 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4867 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4868 brightness = max(0.0000001f, brightness);
4869 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4870 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4871 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4872 current = r_hdr_irisadaptation_value.value;
4874 current = min(current + adjust, goal);
4875 else if (current > goal)
4876 current = max(current - adjust, goal);
4877 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4878 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4880 else if (r_hdr_irisadaptation_value.value != 1.0f)
4881 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4884 static void R_View_SetFrustum(const int *scissor)
4887 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4888 vec3_t forward, left, up, origin, v;
4892 // flipped x coordinates (because x points left here)
4893 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4894 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4896 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4897 switch(vid.renderpath)
4899 case RENDERPATH_D3D9:
4900 case RENDERPATH_D3D10:
4901 case RENDERPATH_D3D11:
4902 case RENDERPATH_SOFT:
4903 // non-flipped y coordinates
4904 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4905 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4907 case RENDERPATH_GL11:
4908 case RENDERPATH_GL13:
4909 case RENDERPATH_GL20:
4910 case RENDERPATH_GLES2:
4911 // non-flipped y coordinates
4912 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4913 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4918 // we can't trust r_refdef.view.forward and friends in reflected scenes
4919 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4922 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4923 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4924 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4925 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4926 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4927 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4928 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4929 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4930 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4931 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4932 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4933 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4937 zNear = r_refdef.nearclip;
4938 nudge = 1.0 - 1.0 / (1<<23);
4939 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4940 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4941 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4942 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4943 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4944 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4945 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4946 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4952 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4953 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4954 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4955 r_refdef.view.frustum[0].dist = m[15] - m[12];
4957 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4958 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4959 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4960 r_refdef.view.frustum[1].dist = m[15] + m[12];
4962 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4963 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4964 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4965 r_refdef.view.frustum[2].dist = m[15] - m[13];
4967 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4968 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4969 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4970 r_refdef.view.frustum[3].dist = m[15] + m[13];
4972 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4973 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4974 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4975 r_refdef.view.frustum[4].dist = m[15] - m[14];
4977 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4978 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4979 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4980 r_refdef.view.frustum[5].dist = m[15] + m[14];
4983 if (r_refdef.view.useperspective)
4985 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4986 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]);
4987 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]);
4988 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]);
4989 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]);
4991 // then the normals from the corners relative to origin
4992 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4993 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4994 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4995 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4997 // in a NORMAL view, forward cross left == up
4998 // in a REFLECTED view, forward cross left == down
4999 // so our cross products above need to be adjusted for a left handed coordinate system
5000 CrossProduct(forward, left, v);
5001 if(DotProduct(v, up) < 0)
5003 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5004 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5005 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5006 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5009 // Leaving those out was a mistake, those were in the old code, and they
5010 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5011 // I couldn't reproduce it after adding those normalizations. --blub
5012 VectorNormalize(r_refdef.view.frustum[0].normal);
5013 VectorNormalize(r_refdef.view.frustum[1].normal);
5014 VectorNormalize(r_refdef.view.frustum[2].normal);
5015 VectorNormalize(r_refdef.view.frustum[3].normal);
5017 // make the corners absolute
5018 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5019 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5020 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5021 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5024 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5026 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5027 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5028 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5029 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5030 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5034 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5035 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5036 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5037 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5038 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5039 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5040 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5041 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5042 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5043 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5045 r_refdef.view.numfrustumplanes = 5;
5047 if (r_refdef.view.useclipplane)
5049 r_refdef.view.numfrustumplanes = 6;
5050 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5053 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5054 PlaneClassify(r_refdef.view.frustum + i);
5056 // LordHavoc: note to all quake engine coders, Quake had a special case
5057 // for 90 degrees which assumed a square view (wrong), so I removed it,
5058 // Quake2 has it disabled as well.
5060 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5061 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5062 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5063 //PlaneClassify(&frustum[0]);
5065 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5066 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5067 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5068 //PlaneClassify(&frustum[1]);
5070 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5071 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5072 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5073 //PlaneClassify(&frustum[2]);
5075 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5076 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5077 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5078 //PlaneClassify(&frustum[3]);
5081 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5082 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5083 //PlaneClassify(&frustum[4]);
5086 void R_View_UpdateWithScissor(const int *myscissor)
5088 R_Main_ResizeViewCache();
5089 R_View_SetFrustum(myscissor);
5090 R_View_WorldVisibility(r_refdef.view.useclipplane);
5091 R_View_UpdateEntityVisible();
5092 R_View_UpdateEntityLighting();
5095 void R_View_Update(void)
5097 R_Main_ResizeViewCache();
5098 R_View_SetFrustum(NULL);
5099 R_View_WorldVisibility(r_refdef.view.useclipplane);
5100 R_View_UpdateEntityVisible();
5101 R_View_UpdateEntityLighting();
5104 void R_SetupView(qboolean allowwaterclippingplane)
5106 const float *customclipplane = NULL;
5108 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5110 // LordHavoc: couldn't figure out how to make this approach the
5111 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5112 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5113 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5114 dist = r_refdef.view.clipplane.dist;
5115 plane[0] = r_refdef.view.clipplane.normal[0];
5116 plane[1] = r_refdef.view.clipplane.normal[1];
5117 plane[2] = r_refdef.view.clipplane.normal[2];
5119 customclipplane = plane;
5122 if (!r_refdef.view.useperspective)
5123 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);
5124 else if (vid.stencil && r_useinfinitefarclip.integer)
5125 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);
5127 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);
5128 R_SetViewport(&r_refdef.view.viewport);
5131 void R_EntityMatrix(const matrix4x4_t *matrix)
5133 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5135 gl_modelmatrixchanged = false;
5136 gl_modelmatrix = *matrix;
5137 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5138 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5139 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5140 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5142 switch(vid.renderpath)
5144 case RENDERPATH_D3D9:
5146 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5147 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5150 case RENDERPATH_D3D10:
5151 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5153 case RENDERPATH_D3D11:
5154 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5156 case RENDERPATH_GL13:
5157 case RENDERPATH_GL11:
5158 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5160 case RENDERPATH_SOFT:
5161 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5162 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5164 case RENDERPATH_GL20:
5165 case RENDERPATH_GLES2:
5166 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5167 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5173 void R_ResetViewRendering2D(void)
5175 r_viewport_t viewport;
5178 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5179 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);
5180 R_SetViewport(&viewport);
5181 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5182 GL_Color(1, 1, 1, 1);
5183 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5184 GL_BlendFunc(GL_ONE, GL_ZERO);
5185 GL_ScissorTest(false);
5186 GL_DepthMask(false);
5187 GL_DepthRange(0, 1);
5188 GL_DepthTest(false);
5189 GL_DepthFunc(GL_LEQUAL);
5190 R_EntityMatrix(&identitymatrix);
5191 R_Mesh_ResetTextureState();
5192 GL_PolygonOffset(0, 0);
5193 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5194 switch(vid.renderpath)
5196 case RENDERPATH_GL11:
5197 case RENDERPATH_GL13:
5198 case RENDERPATH_GL20:
5199 case RENDERPATH_GLES2:
5200 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5202 case RENDERPATH_D3D9:
5203 case RENDERPATH_D3D10:
5204 case RENDERPATH_D3D11:
5205 case RENDERPATH_SOFT:
5208 GL_CullFace(GL_NONE);
5211 void R_ResetViewRendering3D(void)
5216 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5217 GL_Color(1, 1, 1, 1);
5218 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5219 GL_BlendFunc(GL_ONE, GL_ZERO);
5220 GL_ScissorTest(true);
5222 GL_DepthRange(0, 1);
5224 GL_DepthFunc(GL_LEQUAL);
5225 R_EntityMatrix(&identitymatrix);
5226 R_Mesh_ResetTextureState();
5227 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5228 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5229 switch(vid.renderpath)
5231 case RENDERPATH_GL11:
5232 case RENDERPATH_GL13:
5233 case RENDERPATH_GL20:
5234 case RENDERPATH_GLES2:
5235 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5237 case RENDERPATH_D3D9:
5238 case RENDERPATH_D3D10:
5239 case RENDERPATH_D3D11:
5240 case RENDERPATH_SOFT:
5243 GL_CullFace(r_refdef.view.cullface_back);
5248 R_RenderView_UpdateViewVectors
5251 static void R_RenderView_UpdateViewVectors(void)
5253 // break apart the view matrix into vectors for various purposes
5254 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5255 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5256 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5257 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5258 // make an inverted copy of the view matrix for tracking sprites
5259 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5262 void R_RenderScene(void);
5263 void R_RenderWaterPlanes(void);
5265 static void R_Water_StartFrame(void)
5268 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5269 r_waterstate_waterplane_t *p;
5271 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5274 switch(vid.renderpath)
5276 case RENDERPATH_GL20:
5277 case RENDERPATH_D3D9:
5278 case RENDERPATH_D3D10:
5279 case RENDERPATH_D3D11:
5280 case RENDERPATH_SOFT:
5281 case RENDERPATH_GLES2:
5283 case RENDERPATH_GL13:
5284 case RENDERPATH_GL11:
5288 // set waterwidth and waterheight to the water resolution that will be
5289 // used (often less than the screen resolution for faster rendering)
5290 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5291 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5293 // calculate desired texture sizes
5294 // can't use water if the card does not support the texture size
5295 if (!r_water.integer || r_showsurfaces.integer)
5296 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5297 else if (vid.support.arb_texture_non_power_of_two)
5299 texturewidth = waterwidth;
5300 textureheight = waterheight;
5301 camerawidth = waterwidth;
5302 cameraheight = waterheight;
5306 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5307 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5308 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5309 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5312 // allocate textures as needed
5313 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5315 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5316 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5318 if (p->texture_refraction)
5319 R_FreeTexture(p->texture_refraction);
5320 p->texture_refraction = NULL;
5321 if (p->texture_reflection)
5322 R_FreeTexture(p->texture_reflection);
5323 p->texture_reflection = NULL;
5324 if (p->texture_camera)
5325 R_FreeTexture(p->texture_camera);
5326 p->texture_camera = NULL;
5328 memset(&r_waterstate, 0, sizeof(r_waterstate));
5329 r_waterstate.texturewidth = texturewidth;
5330 r_waterstate.textureheight = textureheight;
5331 r_waterstate.camerawidth = camerawidth;
5332 r_waterstate.cameraheight = cameraheight;
5335 if (r_waterstate.texturewidth)
5337 r_waterstate.enabled = true;
5339 // when doing a reduced render (HDR) we want to use a smaller area
5340 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5341 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5343 // set up variables that will be used in shader setup
5344 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5345 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5346 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5347 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5350 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5351 r_waterstate.numwaterplanes = 0;
5354 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5356 int triangleindex, planeindex;
5362 r_waterstate_waterplane_t *p;
5363 texture_t *t = R_GetCurrentTexture(surface->texture);
5365 // just use the first triangle with a valid normal for any decisions
5366 VectorClear(normal);
5367 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5369 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5370 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5371 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5372 TriangleNormal(vert[0], vert[1], vert[2], normal);
5373 if (VectorLength2(normal) >= 0.001)
5377 VectorCopy(normal, plane.normal);
5378 VectorNormalize(plane.normal);
5379 plane.dist = DotProduct(vert[0], plane.normal);
5380 PlaneClassify(&plane);
5381 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5383 // skip backfaces (except if nocullface is set)
5384 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5386 VectorNegate(plane.normal, plane.normal);
5388 PlaneClassify(&plane);
5392 // find a matching plane if there is one
5393 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5394 if(p->camera_entity == t->camera_entity)
5395 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5397 if (planeindex >= r_waterstate.maxwaterplanes)
5398 return; // nothing we can do, out of planes
5400 // if this triangle does not fit any known plane rendered this frame, add one
5401 if (planeindex >= r_waterstate.numwaterplanes)
5403 // store the new plane
5404 r_waterstate.numwaterplanes++;
5406 // clear materialflags and pvs
5407 p->materialflags = 0;
5408 p->pvsvalid = false;
5409 p->camera_entity = t->camera_entity;
5410 VectorCopy(surface->mins, p->mins);
5411 VectorCopy(surface->maxs, p->maxs);
5416 p->mins[0] = min(p->mins[0], surface->mins[0]);
5417 p->mins[1] = min(p->mins[1], surface->mins[1]);
5418 p->mins[2] = min(p->mins[2], surface->mins[2]);
5419 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5420 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5421 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5423 // merge this surface's materialflags into the waterplane
5424 p->materialflags |= t->currentmaterialflags;
5425 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5427 // merge this surface's PVS into the waterplane
5428 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5429 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5430 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5432 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5438 static void R_Water_ProcessPlanes(void)
5441 r_refdef_view_t originalview;
5442 r_refdef_view_t myview;
5444 r_waterstate_waterplane_t *p;
5447 originalview = r_refdef.view;
5449 // make sure enough textures are allocated
5450 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5452 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5454 if (!p->texture_refraction)
5455 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);
5456 if (!p->texture_refraction)
5459 else if (p->materialflags & MATERIALFLAG_CAMERA)
5461 if (!p->texture_camera)
5462 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);
5463 if (!p->texture_camera)
5467 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5469 if (!p->texture_reflection)
5470 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);
5471 if (!p->texture_reflection)
5477 r_refdef.view = originalview;
5478 r_refdef.view.showdebug = false;
5479 r_refdef.view.width = r_waterstate.waterwidth;
5480 r_refdef.view.height = r_waterstate.waterheight;
5481 r_refdef.view.useclipplane = true;
5482 myview = r_refdef.view;
5483 r_waterstate.renderingscene = true;
5484 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5486 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5488 r_refdef.view = myview;
5489 if(r_water_scissormode.integer)
5492 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5493 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5496 // render reflected scene and copy into texture
5497 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5498 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5499 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5500 r_refdef.view.clipplane = p->plane;
5502 // reverse the cullface settings for this render
5503 r_refdef.view.cullface_front = GL_FRONT;
5504 r_refdef.view.cullface_back = GL_BACK;
5505 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5507 r_refdef.view.usecustompvs = true;
5509 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5511 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5514 R_ResetViewRendering3D();
5515 R_ClearScreen(r_refdef.fogenabled);
5516 if(r_water_scissormode.integer & 2)
5517 R_View_UpdateWithScissor(myscissor);
5520 if(r_water_scissormode.integer & 1)
5521 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5524 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);
5527 // render the normal view scene and copy into texture
5528 // (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)
5529 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5531 r_refdef.view = myview;
5532 if(r_water_scissormode.integer)
5535 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5536 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5539 r_waterstate.renderingrefraction = true;
5541 r_refdef.view.clipplane = p->plane;
5542 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5543 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5545 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5547 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5548 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5549 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5550 R_RenderView_UpdateViewVectors();
5551 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5553 r_refdef.view.usecustompvs = true;
5554 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);
5558 PlaneClassify(&r_refdef.view.clipplane);
5560 R_ResetViewRendering3D();
5561 R_ClearScreen(r_refdef.fogenabled);
5562 if(r_water_scissormode.integer & 2)
5563 R_View_UpdateWithScissor(myscissor);
5566 if(r_water_scissormode.integer & 1)
5567 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5570 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);
5571 r_waterstate.renderingrefraction = false;
5573 else if (p->materialflags & MATERIALFLAG_CAMERA)
5575 r_refdef.view = myview;
5577 r_refdef.view.clipplane = p->plane;
5578 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5579 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5581 r_refdef.view.width = r_waterstate.camerawidth;
5582 r_refdef.view.height = r_waterstate.cameraheight;
5583 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5584 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5586 if(p->camera_entity)
5588 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5589 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5592 // note: all of the view is used for displaying... so
5593 // there is no use in scissoring
5595 // reverse the cullface settings for this render
5596 r_refdef.view.cullface_front = GL_FRONT;
5597 r_refdef.view.cullface_back = GL_BACK;
5598 // also reverse the view matrix
5599 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
5600 R_RenderView_UpdateViewVectors();
5601 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5603 r_refdef.view.usecustompvs = true;
5604 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);
5607 // camera needs no clipplane
5608 r_refdef.view.useclipplane = false;
5610 PlaneClassify(&r_refdef.view.clipplane);
5612 R_ResetViewRendering3D();
5613 R_ClearScreen(r_refdef.fogenabled);
5617 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);
5618 r_waterstate.renderingrefraction = false;
5622 r_waterstate.renderingscene = false;
5623 r_refdef.view = originalview;
5624 R_ResetViewRendering3D();
5625 R_ClearScreen(r_refdef.fogenabled);
5629 r_refdef.view = originalview;
5630 r_waterstate.renderingscene = false;
5631 Cvar_SetValueQuick(&r_water, 0);
5632 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5636 void R_Bloom_StartFrame(void)
5638 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5640 switch(vid.renderpath)
5642 case RENDERPATH_GL20:
5643 case RENDERPATH_D3D9:
5644 case RENDERPATH_D3D10:
5645 case RENDERPATH_D3D11:
5646 case RENDERPATH_SOFT:
5647 case RENDERPATH_GLES2:
5649 case RENDERPATH_GL13:
5650 case RENDERPATH_GL11:
5654 // set bloomwidth and bloomheight to the bloom resolution that will be
5655 // used (often less than the screen resolution for faster rendering)
5656 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5657 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5658 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5659 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5660 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5662 // calculate desired texture sizes
5663 if (vid.support.arb_texture_non_power_of_two)
5665 screentexturewidth = r_refdef.view.width;
5666 screentextureheight = r_refdef.view.height;
5667 bloomtexturewidth = r_bloomstate.bloomwidth;
5668 bloomtextureheight = r_bloomstate.bloomheight;
5672 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5673 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5674 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5675 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5678 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))
5680 Cvar_SetValueQuick(&r_hdr, 0);
5681 Cvar_SetValueQuick(&r_bloom, 0);
5682 Cvar_SetValueQuick(&r_motionblur, 0);
5683 Cvar_SetValueQuick(&r_damageblur, 0);
5686 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)))
5687 screentexturewidth = screentextureheight = 0;
5688 if (!r_hdr.integer && !r_bloom.integer)
5689 bloomtexturewidth = bloomtextureheight = 0;
5691 // allocate textures as needed
5692 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5694 if (r_bloomstate.texture_screen)
5695 R_FreeTexture(r_bloomstate.texture_screen);
5696 r_bloomstate.texture_screen = NULL;
5697 r_bloomstate.screentexturewidth = screentexturewidth;
5698 r_bloomstate.screentextureheight = screentextureheight;
5699 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5700 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);
5702 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5704 if (r_bloomstate.texture_bloom)
5705 R_FreeTexture(r_bloomstate.texture_bloom);
5706 r_bloomstate.texture_bloom = NULL;
5707 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5708 r_bloomstate.bloomtextureheight = bloomtextureheight;
5709 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5710 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);
5713 // when doing a reduced render (HDR) we want to use a smaller area
5714 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5715 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5716 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5717 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5718 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5720 // set up a texcoord array for the full resolution screen image
5721 // (we have to keep this around to copy back during final render)
5722 r_bloomstate.screentexcoord2f[0] = 0;
5723 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5724 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5725 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5726 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5727 r_bloomstate.screentexcoord2f[5] = 0;
5728 r_bloomstate.screentexcoord2f[6] = 0;
5729 r_bloomstate.screentexcoord2f[7] = 0;
5731 // set up a texcoord array for the reduced resolution bloom image
5732 // (which will be additive blended over the screen image)
5733 r_bloomstate.bloomtexcoord2f[0] = 0;
5734 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5735 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5736 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5737 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5738 r_bloomstate.bloomtexcoord2f[5] = 0;
5739 r_bloomstate.bloomtexcoord2f[6] = 0;
5740 r_bloomstate.bloomtexcoord2f[7] = 0;
5742 switch(vid.renderpath)
5744 case RENDERPATH_GL11:
5745 case RENDERPATH_GL13:
5746 case RENDERPATH_GL20:
5747 case RENDERPATH_SOFT:
5748 case RENDERPATH_GLES2:
5750 case RENDERPATH_D3D9:
5751 case RENDERPATH_D3D10:
5752 case RENDERPATH_D3D11:
5755 for (i = 0;i < 4;i++)
5757 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5758 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5759 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5760 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5766 if (r_hdr.integer || r_bloom.integer)
5768 r_bloomstate.enabled = true;
5769 r_bloomstate.hdr = r_hdr.integer != 0;
5772 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);
5775 void R_Bloom_CopyBloomTexture(float colorscale)
5777 r_refdef.stats.bloom++;
5779 // scale down screen texture to the bloom texture size
5781 R_SetViewport(&r_bloomstate.viewport);
5782 GL_BlendFunc(GL_ONE, GL_ZERO);
5783 GL_Color(colorscale, colorscale, colorscale, 1);
5784 // 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...
5785 switch(vid.renderpath)
5787 case RENDERPATH_GL11:
5788 case RENDERPATH_GL13:
5789 case RENDERPATH_GL20:
5790 case RENDERPATH_SOFT:
5791 case RENDERPATH_GLES2:
5792 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5794 case RENDERPATH_D3D9:
5795 case RENDERPATH_D3D10:
5796 case RENDERPATH_D3D11:
5797 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5800 // TODO: do boxfilter scale-down in shader?
5801 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5802 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5803 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5805 // we now have a bloom image in the framebuffer
5806 // copy it into the bloom image texture for later processing
5807 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);
5808 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5811 void R_Bloom_CopyHDRTexture(void)
5813 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);
5814 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5817 void R_Bloom_MakeTexture(void)
5820 float xoffset, yoffset, r, brighten;
5822 r_refdef.stats.bloom++;
5824 R_ResetViewRendering2D();
5826 // we have a bloom image in the framebuffer
5828 R_SetViewport(&r_bloomstate.viewport);
5830 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5833 r = bound(0, r_bloom_colorexponent.value / x, 1);
5834 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5836 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5837 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5838 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5839 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5841 // copy the vertically blurred bloom view to a texture
5842 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);
5843 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5846 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5847 brighten = r_bloom_brighten.value;
5849 brighten *= r_hdr_range.value;
5850 brighten = sqrt(brighten);
5852 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5853 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5855 for (dir = 0;dir < 2;dir++)
5857 // blend on at multiple vertical offsets to achieve a vertical blur
5858 // TODO: do offset blends using GLSL
5859 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5860 GL_BlendFunc(GL_ONE, GL_ZERO);
5861 for (x = -range;x <= range;x++)
5863 if (!dir){xoffset = 0;yoffset = x;}
5864 else {xoffset = x;yoffset = 0;}
5865 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5866 yoffset /= (float)r_bloomstate.bloomtextureheight;
5867 // compute a texcoord array with the specified x and y offset
5868 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5869 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5870 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5871 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5872 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5873 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5874 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5875 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5876 // this r value looks like a 'dot' particle, fading sharply to
5877 // black at the edges
5878 // (probably not realistic but looks good enough)
5879 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5880 //r = brighten/(range*2+1);
5881 r = brighten / (range * 2 + 1);
5883 r *= (1 - x*x/(float)(range*range));
5884 GL_Color(r, r, r, 1);
5885 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5886 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5887 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5888 GL_BlendFunc(GL_ONE, GL_ONE);
5891 // copy the vertically blurred bloom view to a texture
5892 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);
5893 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5897 void R_HDR_RenderBloomTexture(void)
5899 int oldwidth, oldheight;
5900 float oldcolorscale;
5901 qboolean oldwaterstate;
5903 oldwaterstate = r_waterstate.enabled;
5904 oldcolorscale = r_refdef.view.colorscale;
5905 oldwidth = r_refdef.view.width;
5906 oldheight = r_refdef.view.height;
5907 r_refdef.view.width = r_bloomstate.bloomwidth;
5908 r_refdef.view.height = r_bloomstate.bloomheight;
5910 if(r_hdr.integer < 2)
5911 r_waterstate.enabled = false;
5913 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5914 // TODO: add exposure compensation features
5915 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5917 r_refdef.view.showdebug = false;
5918 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5920 R_ResetViewRendering3D();
5922 R_ClearScreen(r_refdef.fogenabled);
5923 if (r_timereport_active)
5924 R_TimeReport("HDRclear");
5927 if (r_timereport_active)
5928 R_TimeReport("visibility");
5930 // only do secondary renders with HDR if r_hdr is 2 or higher
5931 r_waterstate.numwaterplanes = 0;
5932 if (r_waterstate.enabled)
5933 R_RenderWaterPlanes();
5935 r_refdef.view.showdebug = true;
5937 r_waterstate.numwaterplanes = 0;
5939 R_ResetViewRendering2D();
5941 R_Bloom_CopyHDRTexture();
5942 R_Bloom_MakeTexture();
5944 // restore the view settings
5945 r_waterstate.enabled = oldwaterstate;
5946 r_refdef.view.width = oldwidth;
5947 r_refdef.view.height = oldheight;
5948 r_refdef.view.colorscale = oldcolorscale;
5950 R_ResetViewRendering3D();
5952 R_ClearScreen(r_refdef.fogenabled);
5953 if (r_timereport_active)
5954 R_TimeReport("viewclear");
5957 static void R_BlendView(void)
5959 unsigned int permutation;
5960 float uservecs[4][4];
5962 switch (vid.renderpath)
5964 case RENDERPATH_GL20:
5965 case RENDERPATH_D3D9:
5966 case RENDERPATH_D3D10:
5967 case RENDERPATH_D3D11:
5968 case RENDERPATH_SOFT:
5969 case RENDERPATH_GLES2:
5971 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5972 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5973 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5974 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5975 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5977 if (r_bloomstate.texture_screen)
5979 // make sure the buffer is available
5980 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5982 R_ResetViewRendering2D();
5984 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5986 // declare variables
5988 static float avgspeed;
5990 speed = VectorLength(cl.movement_velocity);
5992 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5993 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5995 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5996 speed = bound(0, speed, 1);
5997 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5999 // calculate values into a standard alpha
6000 cl.motionbluralpha = 1 - exp(-
6002 (r_motionblur.value * speed / 80)
6004 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6007 max(0.0001, cl.time - cl.oldtime) // fps independent
6010 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6011 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6013 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6015 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6016 GL_Color(1, 1, 1, cl.motionbluralpha);
6017 switch(vid.renderpath)
6019 case RENDERPATH_GL11:
6020 case RENDERPATH_GL13:
6021 case RENDERPATH_GL20:
6022 case RENDERPATH_SOFT:
6023 case RENDERPATH_GLES2:
6024 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6026 case RENDERPATH_D3D9:
6027 case RENDERPATH_D3D10:
6028 case RENDERPATH_D3D11:
6029 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6032 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6033 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6034 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6038 // copy view into the screen texture
6039 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);
6040 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6042 else if (!r_bloomstate.texture_bloom)
6044 // we may still have to do view tint...
6045 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6047 // apply a color tint to the whole view
6048 R_ResetViewRendering2D();
6049 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6050 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6051 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6053 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6055 break; // no screen processing, no bloom, skip it
6058 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6060 // render simple bloom effect
6061 // copy the screen and shrink it and darken it for the bloom process
6062 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6063 // make the bloom texture
6064 R_Bloom_MakeTexture();
6067 #if _MSC_VER >= 1400
6068 #define sscanf sscanf_s
6070 memset(uservecs, 0, sizeof(uservecs));
6071 if (r_glsl_postprocess_uservec1_enable.integer)
6072 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6073 if (r_glsl_postprocess_uservec2_enable.integer)
6074 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6075 if (r_glsl_postprocess_uservec3_enable.integer)
6076 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6077 if (r_glsl_postprocess_uservec4_enable.integer)
6078 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6080 R_ResetViewRendering2D();
6081 GL_Color(1, 1, 1, 1);
6082 GL_BlendFunc(GL_ONE, GL_ZERO);
6084 switch(vid.renderpath)
6086 case RENDERPATH_GL20:
6087 case RENDERPATH_GLES2:
6088 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6089 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6090 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6091 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6092 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6093 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]);
6094 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6095 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]);
6096 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]);
6097 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]);
6098 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]);
6099 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6100 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6101 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);
6103 case RENDERPATH_D3D9:
6105 // 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...
6106 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6107 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6108 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6109 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6110 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6111 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6112 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6113 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6114 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6115 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6116 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6117 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6118 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6119 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6122 case RENDERPATH_D3D10:
6123 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6125 case RENDERPATH_D3D11:
6126 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6128 case RENDERPATH_SOFT:
6129 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6130 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6131 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6132 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6133 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6134 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6135 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6136 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6137 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6138 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6139 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6140 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6141 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6142 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6147 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6148 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6150 case RENDERPATH_GL13:
6151 case RENDERPATH_GL11:
6152 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6154 // apply a color tint to the whole view
6155 R_ResetViewRendering2D();
6156 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6157 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6158 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6159 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6160 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6166 matrix4x4_t r_waterscrollmatrix;
6168 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6170 if (r_refdef.fog_density)
6172 r_refdef.fogcolor[0] = r_refdef.fog_red;
6173 r_refdef.fogcolor[1] = r_refdef.fog_green;
6174 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6176 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6177 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6178 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6179 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6183 VectorCopy(r_refdef.fogcolor, fogvec);
6184 // color.rgb *= ContrastBoost * SceneBrightness;
6185 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6186 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6187 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6188 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6193 void R_UpdateVariables(void)
6197 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6199 r_refdef.farclip = r_farclip_base.value;
6200 if (r_refdef.scene.worldmodel)
6201 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6202 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6204 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6205 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6206 r_refdef.polygonfactor = 0;
6207 r_refdef.polygonoffset = 0;
6208 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6209 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6211 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6212 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6213 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6214 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6215 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6216 if (FAKELIGHT_ENABLED)
6218 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6220 if (r_showsurfaces.integer)
6222 r_refdef.scene.rtworld = false;
6223 r_refdef.scene.rtworldshadows = false;
6224 r_refdef.scene.rtdlight = false;
6225 r_refdef.scene.rtdlightshadows = false;
6226 r_refdef.lightmapintensity = 0;
6229 if (gamemode == GAME_NEHAHRA)
6231 if (gl_fogenable.integer)
6233 r_refdef.oldgl_fogenable = true;
6234 r_refdef.fog_density = gl_fogdensity.value;
6235 r_refdef.fog_red = gl_fogred.value;
6236 r_refdef.fog_green = gl_foggreen.value;
6237 r_refdef.fog_blue = gl_fogblue.value;
6238 r_refdef.fog_alpha = 1;
6239 r_refdef.fog_start = 0;
6240 r_refdef.fog_end = gl_skyclip.value;
6241 r_refdef.fog_height = 1<<30;
6242 r_refdef.fog_fadedepth = 128;
6244 else if (r_refdef.oldgl_fogenable)
6246 r_refdef.oldgl_fogenable = false;
6247 r_refdef.fog_density = 0;
6248 r_refdef.fog_red = 0;
6249 r_refdef.fog_green = 0;
6250 r_refdef.fog_blue = 0;
6251 r_refdef.fog_alpha = 0;
6252 r_refdef.fog_start = 0;
6253 r_refdef.fog_end = 0;
6254 r_refdef.fog_height = 1<<30;
6255 r_refdef.fog_fadedepth = 128;
6259 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6260 r_refdef.fog_start = max(0, r_refdef.fog_start);
6261 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6263 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6265 if (r_refdef.fog_density && r_drawfog.integer)
6267 r_refdef.fogenabled = true;
6268 // this is the point where the fog reaches 0.9986 alpha, which we
6269 // consider a good enough cutoff point for the texture
6270 // (0.9986 * 256 == 255.6)
6271 if (r_fog_exp2.integer)
6272 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6274 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6275 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6276 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6277 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6278 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6279 R_BuildFogHeightTexture();
6280 // fog color was already set
6281 // update the fog texture
6282 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)
6283 R_BuildFogTexture();
6284 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6285 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6288 r_refdef.fogenabled = false;
6290 switch(vid.renderpath)
6292 case RENDERPATH_GL20:
6293 case RENDERPATH_D3D9:
6294 case RENDERPATH_D3D10:
6295 case RENDERPATH_D3D11:
6296 case RENDERPATH_SOFT:
6297 case RENDERPATH_GLES2:
6298 if(v_glslgamma.integer && !vid_gammatables_trivial)
6300 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6302 // build GLSL gamma texture
6303 #define RAMPWIDTH 256
6304 unsigned short ramp[RAMPWIDTH * 3];
6305 unsigned char rampbgr[RAMPWIDTH][4];
6308 r_texture_gammaramps_serial = vid_gammatables_serial;
6310 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6311 for(i = 0; i < RAMPWIDTH; ++i)
6313 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6314 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6315 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6318 if (r_texture_gammaramps)
6320 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6324 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6330 // remove GLSL gamma texture
6333 case RENDERPATH_GL13:
6334 case RENDERPATH_GL11:
6339 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6340 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6346 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6347 if( scenetype != r_currentscenetype ) {
6348 // store the old scenetype
6349 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6350 r_currentscenetype = scenetype;
6351 // move in the new scene
6352 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6361 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6363 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6364 if( scenetype == r_currentscenetype ) {
6365 return &r_refdef.scene;
6367 return &r_scenes_store[ scenetype ];
6376 int dpsoftrast_test;
6377 void R_RenderView(void)
6379 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6381 dpsoftrast_test = r_test.integer;
6383 if (r_timereport_active)
6384 R_TimeReport("start");
6385 r_textureframe++; // used only by R_GetCurrentTexture
6386 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6388 if(R_CompileShader_CheckStaticParms())
6391 if (!r_drawentities.integer)
6392 r_refdef.scene.numentities = 0;
6394 R_AnimCache_ClearCache();
6395 R_FrameData_NewFrame();
6397 /* adjust for stereo display */
6398 if(R_Stereo_Active())
6400 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);
6401 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6404 if (r_refdef.view.isoverlay)
6406 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6407 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6408 R_TimeReport("depthclear");
6410 r_refdef.view.showdebug = false;
6412 r_waterstate.enabled = false;
6413 r_waterstate.numwaterplanes = 0;
6417 r_refdef.view.matrix = originalmatrix;
6423 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6425 r_refdef.view.matrix = originalmatrix;
6426 return; //Host_Error ("R_RenderView: NULL worldmodel");
6429 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6431 R_RenderView_UpdateViewVectors();
6433 R_Shadow_UpdateWorldLightSelection();
6435 R_Bloom_StartFrame();
6436 R_Water_StartFrame();
6439 if (r_timereport_active)
6440 R_TimeReport("viewsetup");
6442 R_ResetViewRendering3D();
6444 if (r_refdef.view.clear || r_refdef.fogenabled)
6446 R_ClearScreen(r_refdef.fogenabled);
6447 if (r_timereport_active)
6448 R_TimeReport("viewclear");
6450 r_refdef.view.clear = true;
6452 // this produces a bloom texture to be used in R_BlendView() later
6453 if (r_hdr.integer && r_bloomstate.bloomwidth)
6455 R_HDR_RenderBloomTexture();
6456 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6457 r_textureframe++; // used only by R_GetCurrentTexture
6460 r_refdef.view.showdebug = true;
6463 if (r_timereport_active)
6464 R_TimeReport("visibility");
6466 r_waterstate.numwaterplanes = 0;
6467 if (r_waterstate.enabled)
6468 R_RenderWaterPlanes();
6471 r_waterstate.numwaterplanes = 0;
6474 if (r_timereport_active)
6475 R_TimeReport("blendview");
6477 GL_Scissor(0, 0, vid.width, vid.height);
6478 GL_ScissorTest(false);
6480 r_refdef.view.matrix = originalmatrix;
6485 void R_RenderWaterPlanes(void)
6487 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6489 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6490 if (r_timereport_active)
6491 R_TimeReport("waterworld");
6494 // don't let sound skip if going slow
6495 if (r_refdef.scene.extraupdate)
6498 R_DrawModelsAddWaterPlanes();
6499 if (r_timereport_active)
6500 R_TimeReport("watermodels");
6502 if (r_waterstate.numwaterplanes)
6504 R_Water_ProcessPlanes();
6505 if (r_timereport_active)
6506 R_TimeReport("waterscenes");
6510 extern void R_DrawLightningBeams (void);
6511 extern void VM_CL_AddPolygonsToMeshQueue (void);
6512 extern void R_DrawPortals (void);
6513 extern cvar_t cl_locs_show;
6514 static void R_DrawLocs(void);
6515 static void R_DrawEntityBBoxes(void);
6516 static void R_DrawModelDecals(void);
6517 extern void R_DrawModelShadows(void);
6518 extern void R_DrawModelShadowMaps(void);
6519 extern cvar_t cl_decals_newsystem;
6520 extern qboolean r_shadow_usingdeferredprepass;
6521 void R_RenderScene(void)
6523 qboolean shadowmapping = false;
6525 if (r_timereport_active)
6526 R_TimeReport("beginscene");
6528 r_refdef.stats.renders++;
6532 // don't let sound skip if going slow
6533 if (r_refdef.scene.extraupdate)
6536 R_MeshQueue_BeginScene();
6540 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);
6542 if (r_timereport_active)
6543 R_TimeReport("skystartframe");
6545 if (cl.csqc_vidvars.drawworld)
6547 // don't let sound skip if going slow
6548 if (r_refdef.scene.extraupdate)
6551 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6553 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6554 if (r_timereport_active)
6555 R_TimeReport("worldsky");
6558 if (R_DrawBrushModelsSky() && r_timereport_active)
6559 R_TimeReport("bmodelsky");
6561 if (skyrendermasked && skyrenderlater)
6563 // we have to force off the water clipping plane while rendering sky
6567 if (r_timereport_active)
6568 R_TimeReport("sky");
6572 R_AnimCache_CacheVisibleEntities();
6573 if (r_timereport_active)
6574 R_TimeReport("animation");
6576 R_Shadow_PrepareLights();
6577 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6578 R_Shadow_PrepareModelShadows();
6579 if (r_timereport_active)
6580 R_TimeReport("preparelights");
6582 if (R_Shadow_ShadowMappingEnabled())
6583 shadowmapping = true;
6585 if (r_shadow_usingdeferredprepass)
6586 R_Shadow_DrawPrepass();
6588 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6590 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6591 if (r_timereport_active)
6592 R_TimeReport("worlddepth");
6594 if (r_depthfirst.integer >= 2)
6596 R_DrawModelsDepth();
6597 if (r_timereport_active)
6598 R_TimeReport("modeldepth");
6601 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6603 R_DrawModelShadowMaps();
6604 R_ResetViewRendering3D();
6605 // don't let sound skip if going slow
6606 if (r_refdef.scene.extraupdate)
6610 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6612 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6613 if (r_timereport_active)
6614 R_TimeReport("world");
6617 // don't let sound skip if going slow
6618 if (r_refdef.scene.extraupdate)
6622 if (r_timereport_active)
6623 R_TimeReport("models");
6625 // don't let sound skip if going slow
6626 if (r_refdef.scene.extraupdate)
6629 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6631 R_DrawModelShadows();
6632 R_ResetViewRendering3D();
6633 // don't let sound skip if going slow
6634 if (r_refdef.scene.extraupdate)
6638 if (!r_shadow_usingdeferredprepass)
6640 R_Shadow_DrawLights();
6641 if (r_timereport_active)
6642 R_TimeReport("rtlights");
6645 // don't let sound skip if going slow
6646 if (r_refdef.scene.extraupdate)
6649 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6651 R_DrawModelShadows();
6652 R_ResetViewRendering3D();
6653 // don't let sound skip if going slow
6654 if (r_refdef.scene.extraupdate)
6658 if (cl.csqc_vidvars.drawworld)
6660 if (cl_decals_newsystem.integer)
6662 R_DrawModelDecals();
6663 if (r_timereport_active)
6664 R_TimeReport("modeldecals");
6669 if (r_timereport_active)
6670 R_TimeReport("decals");
6674 if (r_timereport_active)
6675 R_TimeReport("particles");
6678 if (r_timereport_active)
6679 R_TimeReport("explosions");
6681 R_DrawLightningBeams();
6682 if (r_timereport_active)
6683 R_TimeReport("lightning");
6686 VM_CL_AddPolygonsToMeshQueue();
6688 if (r_refdef.view.showdebug)
6690 if (cl_locs_show.integer)
6693 if (r_timereport_active)
6694 R_TimeReport("showlocs");
6697 if (r_drawportals.integer)
6700 if (r_timereport_active)
6701 R_TimeReport("portals");
6704 if (r_showbboxes.value > 0)
6706 R_DrawEntityBBoxes();
6707 if (r_timereport_active)
6708 R_TimeReport("bboxes");
6712 R_MeshQueue_RenderTransparent();
6713 if (r_timereport_active)
6714 R_TimeReport("drawtrans");
6716 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))
6718 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6719 if (r_timereport_active)
6720 R_TimeReport("worlddebug");
6721 R_DrawModelsDebug();
6722 if (r_timereport_active)
6723 R_TimeReport("modeldebug");
6726 if (cl.csqc_vidvars.drawworld)
6728 R_Shadow_DrawCoronas();
6729 if (r_timereport_active)
6730 R_TimeReport("coronas");
6735 GL_DepthTest(false);
6736 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6737 GL_Color(1, 1, 1, 1);
6738 qglBegin(GL_POLYGON);
6739 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6740 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6741 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6742 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6744 qglBegin(GL_POLYGON);
6745 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]);
6746 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]);
6747 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]);
6748 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]);
6750 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6754 // don't let sound skip if going slow
6755 if (r_refdef.scene.extraupdate)
6758 R_ResetViewRendering2D();
6761 static const unsigned short bboxelements[36] =
6771 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6774 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6776 RSurf_ActiveWorldEntity();
6778 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6779 GL_DepthMask(false);
6780 GL_DepthRange(0, 1);
6781 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6782 // R_Mesh_ResetTextureState();
6784 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6785 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6786 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6787 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6788 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6789 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6790 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6791 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6792 R_FillColors(color4f, 8, cr, cg, cb, ca);
6793 if (r_refdef.fogenabled)
6795 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6797 f1 = RSurf_FogVertex(v);
6799 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6800 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6801 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6804 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6805 R_Mesh_ResetTextureState();
6806 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6807 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6810 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6814 prvm_edict_t *edict;
6815 prvm_prog_t *prog_save = prog;
6817 // this function draws bounding boxes of server entities
6821 GL_CullFace(GL_NONE);
6822 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6826 for (i = 0;i < numsurfaces;i++)
6828 edict = PRVM_EDICT_NUM(surfacelist[i]);
6829 switch ((int)edict->fields.server->solid)
6831 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6832 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6833 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6834 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6835 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6836 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6838 color[3] *= r_showbboxes.value;
6839 color[3] = bound(0, color[3], 1);
6840 GL_DepthTest(!r_showdisabledepthtest.integer);
6841 GL_CullFace(r_refdef.view.cullface_front);
6842 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6848 static void R_DrawEntityBBoxes(void)
6851 prvm_edict_t *edict;
6853 prvm_prog_t *prog_save = prog;
6855 // this function draws bounding boxes of server entities
6861 for (i = 0;i < prog->num_edicts;i++)
6863 edict = PRVM_EDICT_NUM(i);
6864 if (edict->priv.server->free)
6866 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6867 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6869 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6871 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6872 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6878 static const int nomodelelement3i[24] =
6890 static const unsigned short nomodelelement3s[24] =
6902 static const float nomodelvertex3f[6*3] =
6912 static const float nomodelcolor4f[6*4] =
6914 0.0f, 0.0f, 0.5f, 1.0f,
6915 0.0f, 0.0f, 0.5f, 1.0f,
6916 0.0f, 0.5f, 0.0f, 1.0f,
6917 0.0f, 0.5f, 0.0f, 1.0f,
6918 0.5f, 0.0f, 0.0f, 1.0f,
6919 0.5f, 0.0f, 0.0f, 1.0f
6922 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6928 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);
6930 // this is only called once per entity so numsurfaces is always 1, and
6931 // surfacelist is always {0}, so this code does not handle batches
6933 if (rsurface.ent_flags & RENDER_ADDITIVE)
6935 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6936 GL_DepthMask(false);
6938 else if (rsurface.colormod[3] < 1)
6940 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6941 GL_DepthMask(false);
6945 GL_BlendFunc(GL_ONE, GL_ZERO);
6948 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6949 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6950 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6951 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6952 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6953 for (i = 0, c = color4f;i < 6;i++, c += 4)
6955 c[0] *= rsurface.colormod[0];
6956 c[1] *= rsurface.colormod[1];
6957 c[2] *= rsurface.colormod[2];
6958 c[3] *= rsurface.colormod[3];
6960 if (r_refdef.fogenabled)
6962 for (i = 0, c = color4f;i < 6;i++, c += 4)
6964 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6966 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6967 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6968 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6971 // R_Mesh_ResetTextureState();
6972 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6973 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6974 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6977 void R_DrawNoModel(entity_render_t *ent)
6980 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6981 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6982 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6984 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6987 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6989 vec3_t right1, right2, diff, normal;
6991 VectorSubtract (org2, org1, normal);
6993 // calculate 'right' vector for start
6994 VectorSubtract (r_refdef.view.origin, org1, diff);
6995 CrossProduct (normal, diff, right1);
6996 VectorNormalize (right1);
6998 // calculate 'right' vector for end
6999 VectorSubtract (r_refdef.view.origin, org2, diff);
7000 CrossProduct (normal, diff, right2);
7001 VectorNormalize (right2);
7003 vert[ 0] = org1[0] + width * right1[0];
7004 vert[ 1] = org1[1] + width * right1[1];
7005 vert[ 2] = org1[2] + width * right1[2];
7006 vert[ 3] = org1[0] - width * right1[0];
7007 vert[ 4] = org1[1] - width * right1[1];
7008 vert[ 5] = org1[2] - width * right1[2];
7009 vert[ 6] = org2[0] - width * right2[0];
7010 vert[ 7] = org2[1] - width * right2[1];
7011 vert[ 8] = org2[2] - width * right2[2];
7012 vert[ 9] = org2[0] + width * right2[0];
7013 vert[10] = org2[1] + width * right2[1];
7014 vert[11] = org2[2] + width * right2[2];
7017 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)
7019 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7020 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7021 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7022 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7023 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7024 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7025 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7026 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7027 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7028 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7029 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7030 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7033 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7038 VectorSet(v, x, y, z);
7039 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7040 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7042 if (i == mesh->numvertices)
7044 if (mesh->numvertices < mesh->maxvertices)
7046 VectorCopy(v, vertex3f);
7047 mesh->numvertices++;
7049 return mesh->numvertices;
7055 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7059 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7060 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7061 e = mesh->element3i + mesh->numtriangles * 3;
7062 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7064 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7065 if (mesh->numtriangles < mesh->maxtriangles)
7070 mesh->numtriangles++;
7072 element[1] = element[2];
7076 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7080 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7081 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7082 e = mesh->element3i + mesh->numtriangles * 3;
7083 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7085 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7086 if (mesh->numtriangles < mesh->maxtriangles)
7091 mesh->numtriangles++;
7093 element[1] = element[2];
7097 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7098 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7100 int planenum, planenum2;
7103 mplane_t *plane, *plane2;
7105 double temppoints[2][256*3];
7106 // figure out how large a bounding box we need to properly compute this brush
7108 for (w = 0;w < numplanes;w++)
7109 maxdist = max(maxdist, fabs(planes[w].dist));
7110 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7111 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7112 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7116 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7117 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7119 if (planenum2 == planenum)
7121 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);
7124 if (tempnumpoints < 3)
7126 // generate elements forming a triangle fan for this polygon
7127 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7131 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)
7133 texturelayer_t *layer;
7134 layer = t->currentlayers + t->currentnumlayers++;
7136 layer->depthmask = depthmask;
7137 layer->blendfunc1 = blendfunc1;
7138 layer->blendfunc2 = blendfunc2;
7139 layer->texture = texture;
7140 layer->texmatrix = *matrix;
7141 layer->color[0] = r;
7142 layer->color[1] = g;
7143 layer->color[2] = b;
7144 layer->color[3] = a;
7147 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7149 if(parms[0] == 0 && parms[1] == 0)
7151 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7152 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7157 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7160 index = parms[2] + r_refdef.scene.time * parms[3];
7161 index -= floor(index);
7162 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7165 case Q3WAVEFUNC_NONE:
7166 case Q3WAVEFUNC_NOISE:
7167 case Q3WAVEFUNC_COUNT:
7170 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7171 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7172 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7173 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7174 case Q3WAVEFUNC_TRIANGLE:
7176 f = index - floor(index);
7187 f = parms[0] + parms[1] * f;
7188 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7189 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7193 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7198 matrix4x4_t matrix, temp;
7199 switch(tcmod->tcmod)
7203 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7204 matrix = r_waterscrollmatrix;
7206 matrix = identitymatrix;
7208 case Q3TCMOD_ENTITYTRANSLATE:
7209 // this is used in Q3 to allow the gamecode to control texcoord
7210 // scrolling on the entity, which is not supported in darkplaces yet.
7211 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7213 case Q3TCMOD_ROTATE:
7214 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7215 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7216 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7219 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7221 case Q3TCMOD_SCROLL:
7222 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7224 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7225 w = (int) tcmod->parms[0];
7226 h = (int) tcmod->parms[1];
7227 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7229 idx = (int) floor(f * w * h);
7230 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7232 case Q3TCMOD_STRETCH:
7233 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7234 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7236 case Q3TCMOD_TRANSFORM:
7237 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7238 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7239 VectorSet(tcmat + 6, 0 , 0 , 1);
7240 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7241 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7243 case Q3TCMOD_TURBULENT:
7244 // this is handled in the RSurf_PrepareVertices function
7245 matrix = identitymatrix;
7249 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7252 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7254 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7255 char name[MAX_QPATH];
7256 skinframe_t *skinframe;
7257 unsigned char pixels[296*194];
7258 strlcpy(cache->name, skinname, sizeof(cache->name));
7259 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7260 if (developer_loading.integer)
7261 Con_Printf("loading %s\n", name);
7262 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7263 if (!skinframe || !skinframe->base)
7266 fs_offset_t filesize;
7268 f = FS_LoadFile(name, tempmempool, true, &filesize);
7271 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7272 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7276 cache->skinframe = skinframe;
7279 texture_t *R_GetCurrentTexture(texture_t *t)
7282 const entity_render_t *ent = rsurface.entity;
7283 dp_model_t *model = ent->model;
7284 q3shaderinfo_layer_tcmod_t *tcmod;
7286 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7287 return t->currentframe;
7288 t->update_lastrenderframe = r_textureframe;
7289 t->update_lastrenderentity = (void *)ent;
7291 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7292 t->camera_entity = ent->entitynumber;
7294 t->camera_entity = 0;
7296 // switch to an alternate material if this is a q1bsp animated material
7298 texture_t *texture = t;
7299 int s = rsurface.ent_skinnum;
7300 if ((unsigned int)s >= (unsigned int)model->numskins)
7302 if (model->skinscenes)
7304 if (model->skinscenes[s].framecount > 1)
7305 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7307 s = model->skinscenes[s].firstframe;
7310 t = t + s * model->num_surfaces;
7313 // use an alternate animation if the entity's frame is not 0,
7314 // and only if the texture has an alternate animation
7315 if (rsurface.ent_alttextures && t->anim_total[1])
7316 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7318 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7320 texture->currentframe = t;
7323 // update currentskinframe to be a qw skin or animation frame
7324 if (rsurface.ent_qwskin >= 0)
7326 i = rsurface.ent_qwskin;
7327 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7329 r_qwskincache_size = cl.maxclients;
7331 Mem_Free(r_qwskincache);
7332 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7334 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7335 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7336 t->currentskinframe = r_qwskincache[i].skinframe;
7337 if (t->currentskinframe == NULL)
7338 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7340 else if (t->numskinframes >= 2)
7341 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7342 if (t->backgroundnumskinframes >= 2)
7343 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7345 t->currentmaterialflags = t->basematerialflags;
7346 t->currentalpha = rsurface.colormod[3];
7347 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7348 t->currentalpha *= r_wateralpha.value;
7349 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7350 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7351 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7352 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7353 if (!(rsurface.ent_flags & RENDER_LIGHT))
7354 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7355 else if (FAKELIGHT_ENABLED)
7357 // no modellight if using fakelight for the map
7359 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7361 // pick a model lighting mode
7362 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7363 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7365 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7367 if (rsurface.ent_flags & RENDER_ADDITIVE)
7368 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7369 else if (t->currentalpha < 1)
7370 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7371 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7372 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7373 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7374 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7375 if (t->backgroundnumskinframes)
7376 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7377 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7379 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7380 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7383 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7384 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7385 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7387 // there is no tcmod
7388 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7390 t->currenttexmatrix = r_waterscrollmatrix;
7391 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7393 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7395 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7396 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7399 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7400 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7401 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7402 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7404 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7405 if (t->currentskinframe->qpixels)
7406 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7407 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7408 if (!t->basetexture)
7409 t->basetexture = r_texture_notexture;
7410 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7411 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7412 t->nmaptexture = t->currentskinframe->nmap;
7413 if (!t->nmaptexture)
7414 t->nmaptexture = r_texture_blanknormalmap;
7415 t->glosstexture = r_texture_black;
7416 t->glowtexture = t->currentskinframe->glow;
7417 t->fogtexture = t->currentskinframe->fog;
7418 t->reflectmasktexture = t->currentskinframe->reflect;
7419 if (t->backgroundnumskinframes)
7421 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7422 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7423 t->backgroundglosstexture = r_texture_black;
7424 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7425 if (!t->backgroundnmaptexture)
7426 t->backgroundnmaptexture = r_texture_blanknormalmap;
7430 t->backgroundbasetexture = r_texture_white;
7431 t->backgroundnmaptexture = r_texture_blanknormalmap;
7432 t->backgroundglosstexture = r_texture_black;
7433 t->backgroundglowtexture = NULL;
7435 t->specularpower = r_shadow_glossexponent.value;
7436 // TODO: store reference values for these in the texture?
7437 t->specularscale = 0;
7438 if (r_shadow_gloss.integer > 0)
7440 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7442 if (r_shadow_glossintensity.value > 0)
7444 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7445 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7446 t->specularscale = r_shadow_glossintensity.value;
7449 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7451 t->glosstexture = r_texture_white;
7452 t->backgroundglosstexture = r_texture_white;
7453 t->specularscale = r_shadow_gloss2intensity.value;
7454 t->specularpower = r_shadow_gloss2exponent.value;
7457 t->specularscale *= t->specularscalemod;
7458 t->specularpower *= t->specularpowermod;
7460 // lightmaps mode looks bad with dlights using actual texturing, so turn
7461 // off the colormap and glossmap, but leave the normalmap on as it still
7462 // accurately represents the shading involved
7463 if (gl_lightmaps.integer)
7465 t->basetexture = r_texture_grey128;
7466 t->pantstexture = r_texture_black;
7467 t->shirttexture = r_texture_black;
7468 t->nmaptexture = r_texture_blanknormalmap;
7469 t->glosstexture = r_texture_black;
7470 t->glowtexture = NULL;
7471 t->fogtexture = NULL;
7472 t->reflectmasktexture = NULL;
7473 t->backgroundbasetexture = NULL;
7474 t->backgroundnmaptexture = r_texture_blanknormalmap;
7475 t->backgroundglosstexture = r_texture_black;
7476 t->backgroundglowtexture = NULL;
7477 t->specularscale = 0;
7478 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7481 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7482 VectorClear(t->dlightcolor);
7483 t->currentnumlayers = 0;
7484 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7486 int blendfunc1, blendfunc2;
7488 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7490 blendfunc1 = GL_SRC_ALPHA;
7491 blendfunc2 = GL_ONE;
7493 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7495 blendfunc1 = GL_SRC_ALPHA;
7496 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7498 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7500 blendfunc1 = t->customblendfunc[0];
7501 blendfunc2 = t->customblendfunc[1];
7505 blendfunc1 = GL_ONE;
7506 blendfunc2 = GL_ZERO;
7508 // don't colormod evilblend textures
7509 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7510 VectorSet(t->lightmapcolor, 1, 1, 1);
7511 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7512 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7514 // fullbright is not affected by r_refdef.lightmapintensity
7515 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]);
7516 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7517 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]);
7518 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7519 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]);
7523 vec3_t ambientcolor;
7525 // set the color tint used for lights affecting this surface
7526 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7528 // q3bsp has no lightmap updates, so the lightstylevalue that
7529 // would normally be baked into the lightmap must be
7530 // applied to the color
7531 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7532 if (model->type == mod_brushq3)
7533 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7534 colorscale *= r_refdef.lightmapintensity;
7535 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7536 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7537 // basic lit geometry
7538 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]);
7539 // add pants/shirt if needed
7540 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7541 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]);
7542 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7543 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]);
7544 // now add ambient passes if needed
7545 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7547 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]);
7548 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7549 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]);
7550 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7551 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]);
7554 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7555 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]);
7556 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7558 // if this is opaque use alpha blend which will darken the earlier
7561 // if this is an alpha blended material, all the earlier passes
7562 // were darkened by fog already, so we only need to add the fog
7563 // color ontop through the fog mask texture
7565 // if this is an additive blended material, all the earlier passes
7566 // were darkened by fog already, and we should not add fog color
7567 // (because the background was not darkened, there is no fog color
7568 // that was lost behind it).
7569 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]);
7573 return t->currentframe;
7576 rsurfacestate_t rsurface;
7578 void RSurf_ActiveWorldEntity(void)
7580 dp_model_t *model = r_refdef.scene.worldmodel;
7581 //if (rsurface.entity == r_refdef.scene.worldentity)
7583 rsurface.entity = r_refdef.scene.worldentity;
7584 rsurface.skeleton = NULL;
7585 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7586 rsurface.ent_skinnum = 0;
7587 rsurface.ent_qwskin = -1;
7588 rsurface.ent_shadertime = 0;
7589 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7590 rsurface.matrix = identitymatrix;
7591 rsurface.inversematrix = identitymatrix;
7592 rsurface.matrixscale = 1;
7593 rsurface.inversematrixscale = 1;
7594 R_EntityMatrix(&identitymatrix);
7595 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7596 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7597 rsurface.fograngerecip = r_refdef.fograngerecip;
7598 rsurface.fogheightfade = r_refdef.fogheightfade;
7599 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7600 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7601 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7602 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7603 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7604 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7605 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7606 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7607 rsurface.colormod[3] = 1;
7608 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);
7609 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7610 rsurface.frameblend[0].lerp = 1;
7611 rsurface.ent_alttextures = false;
7612 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7613 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7614 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7615 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7616 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7617 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7618 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7619 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7620 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7621 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7622 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7623 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7624 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7625 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7626 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7627 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7628 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7629 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7630 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7631 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7632 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7633 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7634 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7635 rsurface.modelelement3i = model->surfmesh.data_element3i;
7636 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7637 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7638 rsurface.modelelement3s = model->surfmesh.data_element3s;
7639 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7640 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7641 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7642 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7643 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7644 rsurface.modelsurfaces = model->data_surfaces;
7645 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7646 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7647 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7648 rsurface.modelgeneratedvertex = false;
7649 rsurface.batchgeneratedvertex = false;
7650 rsurface.batchfirstvertex = 0;
7651 rsurface.batchnumvertices = 0;
7652 rsurface.batchfirsttriangle = 0;
7653 rsurface.batchnumtriangles = 0;
7654 rsurface.batchvertex3f = NULL;
7655 rsurface.batchvertex3f_vertexbuffer = NULL;
7656 rsurface.batchvertex3f_bufferoffset = 0;
7657 rsurface.batchsvector3f = NULL;
7658 rsurface.batchsvector3f_vertexbuffer = NULL;
7659 rsurface.batchsvector3f_bufferoffset = 0;
7660 rsurface.batchtvector3f = NULL;
7661 rsurface.batchtvector3f_vertexbuffer = NULL;
7662 rsurface.batchtvector3f_bufferoffset = 0;
7663 rsurface.batchnormal3f = NULL;
7664 rsurface.batchnormal3f_vertexbuffer = NULL;
7665 rsurface.batchnormal3f_bufferoffset = 0;
7666 rsurface.batchlightmapcolor4f = NULL;
7667 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7668 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7669 rsurface.batchtexcoordtexture2f = NULL;
7670 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7671 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7672 rsurface.batchtexcoordlightmap2f = NULL;
7673 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7674 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7675 rsurface.batchvertexmesh = NULL;
7676 rsurface.batchvertexmeshbuffer = NULL;
7677 rsurface.batchvertex3fbuffer = NULL;
7678 rsurface.batchelement3i = NULL;
7679 rsurface.batchelement3i_indexbuffer = NULL;
7680 rsurface.batchelement3i_bufferoffset = 0;
7681 rsurface.batchelement3s = NULL;
7682 rsurface.batchelement3s_indexbuffer = NULL;
7683 rsurface.batchelement3s_bufferoffset = 0;
7684 rsurface.passcolor4f = NULL;
7685 rsurface.passcolor4f_vertexbuffer = NULL;
7686 rsurface.passcolor4f_bufferoffset = 0;
7689 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7691 dp_model_t *model = ent->model;
7692 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7694 rsurface.entity = (entity_render_t *)ent;
7695 rsurface.skeleton = ent->skeleton;
7696 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7697 rsurface.ent_skinnum = ent->skinnum;
7698 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;
7699 rsurface.ent_shadertime = ent->shadertime;
7700 rsurface.ent_flags = ent->flags;
7701 rsurface.matrix = ent->matrix;
7702 rsurface.inversematrix = ent->inversematrix;
7703 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7704 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7705 R_EntityMatrix(&rsurface.matrix);
7706 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7707 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7708 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7709 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7710 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7711 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7712 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7713 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7714 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7715 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7716 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7717 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7718 rsurface.colormod[3] = ent->alpha;
7719 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7720 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7721 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7722 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7723 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7724 if (ent->model->brush.submodel && !prepass)
7726 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7727 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7729 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7731 if (ent->animcache_vertex3f)
7733 rsurface.modelvertex3f = ent->animcache_vertex3f;
7734 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7735 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7736 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7737 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7738 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7739 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7741 else if (wanttangents)
7743 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7744 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7745 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7746 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7747 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7748 rsurface.modelvertexmesh = NULL;
7749 rsurface.modelvertexmeshbuffer = NULL;
7750 rsurface.modelvertex3fbuffer = NULL;
7752 else if (wantnormals)
7754 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7755 rsurface.modelsvector3f = NULL;
7756 rsurface.modeltvector3f = NULL;
7757 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7758 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7759 rsurface.modelvertexmesh = NULL;
7760 rsurface.modelvertexmeshbuffer = NULL;
7761 rsurface.modelvertex3fbuffer = NULL;
7765 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7766 rsurface.modelsvector3f = NULL;
7767 rsurface.modeltvector3f = NULL;
7768 rsurface.modelnormal3f = NULL;
7769 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7770 rsurface.modelvertexmesh = NULL;
7771 rsurface.modelvertexmeshbuffer = NULL;
7772 rsurface.modelvertex3fbuffer = NULL;
7774 rsurface.modelvertex3f_vertexbuffer = 0;
7775 rsurface.modelvertex3f_bufferoffset = 0;
7776 rsurface.modelsvector3f_vertexbuffer = 0;
7777 rsurface.modelsvector3f_bufferoffset = 0;
7778 rsurface.modeltvector3f_vertexbuffer = 0;
7779 rsurface.modeltvector3f_bufferoffset = 0;
7780 rsurface.modelnormal3f_vertexbuffer = 0;
7781 rsurface.modelnormal3f_bufferoffset = 0;
7782 rsurface.modelgeneratedvertex = true;
7786 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7787 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7788 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7789 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7790 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7791 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7792 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7793 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7794 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7795 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7796 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7797 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7798 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7799 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7800 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7801 rsurface.modelgeneratedvertex = false;
7803 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7804 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7805 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7806 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7807 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7808 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7809 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7810 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7811 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7812 rsurface.modelelement3i = model->surfmesh.data_element3i;
7813 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7814 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7815 rsurface.modelelement3s = model->surfmesh.data_element3s;
7816 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7817 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7818 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7819 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7820 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7821 rsurface.modelsurfaces = model->data_surfaces;
7822 rsurface.batchgeneratedvertex = false;
7823 rsurface.batchfirstvertex = 0;
7824 rsurface.batchnumvertices = 0;
7825 rsurface.batchfirsttriangle = 0;
7826 rsurface.batchnumtriangles = 0;
7827 rsurface.batchvertex3f = NULL;
7828 rsurface.batchvertex3f_vertexbuffer = NULL;
7829 rsurface.batchvertex3f_bufferoffset = 0;
7830 rsurface.batchsvector3f = NULL;
7831 rsurface.batchsvector3f_vertexbuffer = NULL;
7832 rsurface.batchsvector3f_bufferoffset = 0;
7833 rsurface.batchtvector3f = NULL;
7834 rsurface.batchtvector3f_vertexbuffer = NULL;
7835 rsurface.batchtvector3f_bufferoffset = 0;
7836 rsurface.batchnormal3f = NULL;
7837 rsurface.batchnormal3f_vertexbuffer = NULL;
7838 rsurface.batchnormal3f_bufferoffset = 0;
7839 rsurface.batchlightmapcolor4f = NULL;
7840 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7841 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7842 rsurface.batchtexcoordtexture2f = NULL;
7843 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7844 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7845 rsurface.batchtexcoordlightmap2f = NULL;
7846 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7847 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7848 rsurface.batchvertexmesh = NULL;
7849 rsurface.batchvertexmeshbuffer = NULL;
7850 rsurface.batchvertex3fbuffer = NULL;
7851 rsurface.batchelement3i = NULL;
7852 rsurface.batchelement3i_indexbuffer = NULL;
7853 rsurface.batchelement3i_bufferoffset = 0;
7854 rsurface.batchelement3s = NULL;
7855 rsurface.batchelement3s_indexbuffer = NULL;
7856 rsurface.batchelement3s_bufferoffset = 0;
7857 rsurface.passcolor4f = NULL;
7858 rsurface.passcolor4f_vertexbuffer = NULL;
7859 rsurface.passcolor4f_bufferoffset = 0;
7862 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)
7864 rsurface.entity = r_refdef.scene.worldentity;
7865 rsurface.skeleton = NULL;
7866 rsurface.ent_skinnum = 0;
7867 rsurface.ent_qwskin = -1;
7868 rsurface.ent_shadertime = shadertime;
7869 rsurface.ent_flags = entflags;
7870 rsurface.modelnumvertices = numvertices;
7871 rsurface.modelnumtriangles = numtriangles;
7872 rsurface.matrix = *matrix;
7873 rsurface.inversematrix = *inversematrix;
7874 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7875 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7876 R_EntityMatrix(&rsurface.matrix);
7877 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7878 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7879 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7880 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7881 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7882 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7883 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7884 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7885 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7886 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7887 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7888 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7889 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);
7890 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7891 rsurface.frameblend[0].lerp = 1;
7892 rsurface.ent_alttextures = false;
7893 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7894 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7897 rsurface.modelvertex3f = (float *)vertex3f;
7898 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7899 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7900 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7902 else if (wantnormals)
7904 rsurface.modelvertex3f = (float *)vertex3f;
7905 rsurface.modelsvector3f = NULL;
7906 rsurface.modeltvector3f = NULL;
7907 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7911 rsurface.modelvertex3f = (float *)vertex3f;
7912 rsurface.modelsvector3f = NULL;
7913 rsurface.modeltvector3f = NULL;
7914 rsurface.modelnormal3f = NULL;
7916 rsurface.modelvertexmesh = NULL;
7917 rsurface.modelvertexmeshbuffer = NULL;
7918 rsurface.modelvertex3fbuffer = NULL;
7919 rsurface.modelvertex3f_vertexbuffer = 0;
7920 rsurface.modelvertex3f_bufferoffset = 0;
7921 rsurface.modelsvector3f_vertexbuffer = 0;
7922 rsurface.modelsvector3f_bufferoffset = 0;
7923 rsurface.modeltvector3f_vertexbuffer = 0;
7924 rsurface.modeltvector3f_bufferoffset = 0;
7925 rsurface.modelnormal3f_vertexbuffer = 0;
7926 rsurface.modelnormal3f_bufferoffset = 0;
7927 rsurface.modelgeneratedvertex = true;
7928 rsurface.modellightmapcolor4f = (float *)color4f;
7929 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7930 rsurface.modellightmapcolor4f_bufferoffset = 0;
7931 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7932 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7933 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7934 rsurface.modeltexcoordlightmap2f = NULL;
7935 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7936 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7937 rsurface.modelelement3i = (int *)element3i;
7938 rsurface.modelelement3i_indexbuffer = NULL;
7939 rsurface.modelelement3i_bufferoffset = 0;
7940 rsurface.modelelement3s = (unsigned short *)element3s;
7941 rsurface.modelelement3s_indexbuffer = NULL;
7942 rsurface.modelelement3s_bufferoffset = 0;
7943 rsurface.modellightmapoffsets = NULL;
7944 rsurface.modelsurfaces = NULL;
7945 rsurface.batchgeneratedvertex = false;
7946 rsurface.batchfirstvertex = 0;
7947 rsurface.batchnumvertices = 0;
7948 rsurface.batchfirsttriangle = 0;
7949 rsurface.batchnumtriangles = 0;
7950 rsurface.batchvertex3f = NULL;
7951 rsurface.batchvertex3f_vertexbuffer = NULL;
7952 rsurface.batchvertex3f_bufferoffset = 0;
7953 rsurface.batchsvector3f = NULL;
7954 rsurface.batchsvector3f_vertexbuffer = NULL;
7955 rsurface.batchsvector3f_bufferoffset = 0;
7956 rsurface.batchtvector3f = NULL;
7957 rsurface.batchtvector3f_vertexbuffer = NULL;
7958 rsurface.batchtvector3f_bufferoffset = 0;
7959 rsurface.batchnormal3f = NULL;
7960 rsurface.batchnormal3f_vertexbuffer = NULL;
7961 rsurface.batchnormal3f_bufferoffset = 0;
7962 rsurface.batchlightmapcolor4f = NULL;
7963 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7964 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7965 rsurface.batchtexcoordtexture2f = NULL;
7966 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7967 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7968 rsurface.batchtexcoordlightmap2f = NULL;
7969 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7970 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7971 rsurface.batchvertexmesh = NULL;
7972 rsurface.batchvertexmeshbuffer = NULL;
7973 rsurface.batchvertex3fbuffer = NULL;
7974 rsurface.batchelement3i = NULL;
7975 rsurface.batchelement3i_indexbuffer = NULL;
7976 rsurface.batchelement3i_bufferoffset = 0;
7977 rsurface.batchelement3s = NULL;
7978 rsurface.batchelement3s_indexbuffer = NULL;
7979 rsurface.batchelement3s_bufferoffset = 0;
7980 rsurface.passcolor4f = NULL;
7981 rsurface.passcolor4f_vertexbuffer = NULL;
7982 rsurface.passcolor4f_bufferoffset = 0;
7984 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7986 if ((wantnormals || wanttangents) && !normal3f)
7988 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7989 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7991 if (wanttangents && !svector3f)
7993 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7994 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7995 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8000 float RSurf_FogPoint(const float *v)
8002 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8003 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8004 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8005 float FogHeightFade = r_refdef.fogheightfade;
8007 unsigned int fogmasktableindex;
8008 if (r_refdef.fogplaneviewabove)
8009 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8011 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8012 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8013 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8016 float RSurf_FogVertex(const float *v)
8018 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8019 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8020 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8021 float FogHeightFade = rsurface.fogheightfade;
8023 unsigned int fogmasktableindex;
8024 if (r_refdef.fogplaneviewabove)
8025 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8027 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8028 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8029 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8032 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8035 for (i = 0;i < numelements;i++)
8036 outelement3i[i] = inelement3i[i] + adjust;
8039 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8040 extern cvar_t gl_vbo;
8041 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8049 int surfacefirsttriangle;
8050 int surfacenumtriangles;
8051 int surfacefirstvertex;
8052 int surfaceendvertex;
8053 int surfacenumvertices;
8054 int batchnumvertices;
8055 int batchnumtriangles;
8059 qboolean dynamicvertex;
8063 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8065 q3shaderinfo_deform_t *deform;
8066 const msurface_t *surface, *firstsurface;
8067 r_vertexmesh_t *vertexmesh;
8068 if (!texturenumsurfaces)
8070 // find vertex range of this surface batch
8072 firstsurface = texturesurfacelist[0];
8073 firsttriangle = firstsurface->num_firsttriangle;
8074 batchnumvertices = 0;
8075 batchnumtriangles = 0;
8076 firstvertex = endvertex = firstsurface->num_firstvertex;
8077 for (i = 0;i < texturenumsurfaces;i++)
8079 surface = texturesurfacelist[i];
8080 if (surface != firstsurface + i)
8082 surfacefirstvertex = surface->num_firstvertex;
8083 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8084 surfacenumvertices = surface->num_vertices;
8085 surfacenumtriangles = surface->num_triangles;
8086 if (firstvertex > surfacefirstvertex)
8087 firstvertex = surfacefirstvertex;
8088 if (endvertex < surfaceendvertex)
8089 endvertex = surfaceendvertex;
8090 batchnumvertices += surfacenumvertices;
8091 batchnumtriangles += surfacenumtriangles;
8094 // we now know the vertex range used, and if there are any gaps in it
8095 rsurface.batchfirstvertex = firstvertex;
8096 rsurface.batchnumvertices = endvertex - firstvertex;
8097 rsurface.batchfirsttriangle = firsttriangle;
8098 rsurface.batchnumtriangles = batchnumtriangles;
8100 // this variable holds flags for which properties have been updated that
8101 // may require regenerating vertexmesh array...
8104 // check if any dynamic vertex processing must occur
8105 dynamicvertex = false;
8107 // if there is a chance of animated vertex colors, it's a dynamic batch
8108 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8110 dynamicvertex = true;
8111 batchneed |= BATCHNEED_NOGAPS;
8112 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8115 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8117 switch (deform->deform)
8120 case Q3DEFORM_PROJECTIONSHADOW:
8121 case Q3DEFORM_TEXT0:
8122 case Q3DEFORM_TEXT1:
8123 case Q3DEFORM_TEXT2:
8124 case Q3DEFORM_TEXT3:
8125 case Q3DEFORM_TEXT4:
8126 case Q3DEFORM_TEXT5:
8127 case Q3DEFORM_TEXT6:
8128 case Q3DEFORM_TEXT7:
8131 case Q3DEFORM_AUTOSPRITE:
8132 dynamicvertex = true;
8133 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8134 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8136 case Q3DEFORM_AUTOSPRITE2:
8137 dynamicvertex = true;
8138 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8139 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8141 case Q3DEFORM_NORMAL:
8142 dynamicvertex = true;
8143 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8144 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8147 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8148 break; // if wavefunc is a nop, ignore this transform
8149 dynamicvertex = true;
8150 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8151 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8153 case Q3DEFORM_BULGE:
8154 dynamicvertex = true;
8155 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8156 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8159 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8160 break; // if wavefunc is a nop, ignore this transform
8161 dynamicvertex = true;
8162 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8163 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8167 switch(rsurface.texture->tcgen.tcgen)
8170 case Q3TCGEN_TEXTURE:
8172 case Q3TCGEN_LIGHTMAP:
8173 dynamicvertex = true;
8174 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8175 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8177 case Q3TCGEN_VECTOR:
8178 dynamicvertex = true;
8179 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8180 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8182 case Q3TCGEN_ENVIRONMENT:
8183 dynamicvertex = true;
8184 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8185 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8188 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8190 dynamicvertex = true;
8191 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8192 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8195 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8197 dynamicvertex = true;
8198 batchneed |= BATCHNEED_NOGAPS;
8199 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8202 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8204 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8205 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8206 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8207 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8208 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8209 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8210 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8213 // when the model data has no vertex buffer (dynamic mesh), we need to
8215 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8216 batchneed |= BATCHNEED_NOGAPS;
8218 // if needsupdate, we have to do a dynamic vertex batch for sure
8219 if (needsupdate & batchneed)
8220 dynamicvertex = true;
8222 // see if we need to build vertexmesh from arrays
8223 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8224 dynamicvertex = true;
8226 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8227 // also some drivers strongly dislike firstvertex
8228 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8229 dynamicvertex = true;
8231 rsurface.batchvertex3f = rsurface.modelvertex3f;
8232 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8233 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8234 rsurface.batchsvector3f = rsurface.modelsvector3f;
8235 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8236 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8237 rsurface.batchtvector3f = rsurface.modeltvector3f;
8238 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8239 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8240 rsurface.batchnormal3f = rsurface.modelnormal3f;
8241 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8242 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8243 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8244 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8245 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8246 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8247 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8248 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8249 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8250 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8251 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8252 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8253 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8254 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8255 rsurface.batchelement3i = rsurface.modelelement3i;
8256 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8257 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8258 rsurface.batchelement3s = rsurface.modelelement3s;
8259 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8260 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8262 // if any dynamic vertex processing has to occur in software, we copy the
8263 // entire surface list together before processing to rebase the vertices
8264 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8266 // if any gaps exist and we do not have a static vertex buffer, we have to
8267 // copy the surface list together to avoid wasting upload bandwidth on the
8268 // vertices in the gaps.
8270 // if gaps exist and we have a static vertex buffer, we still have to
8271 // combine the index buffer ranges into one dynamic index buffer.
8273 // in all cases we end up with data that can be drawn in one call.
8277 // static vertex data, just set pointers...
8278 rsurface.batchgeneratedvertex = false;
8279 // if there are gaps, we want to build a combined index buffer,
8280 // otherwise use the original static buffer with an appropriate offset
8283 // build a new triangle elements array for this batch
8284 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8285 rsurface.batchfirsttriangle = 0;
8287 for (i = 0;i < texturenumsurfaces;i++)
8289 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8290 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8291 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8292 numtriangles += surfacenumtriangles;
8294 rsurface.batchelement3i_indexbuffer = NULL;
8295 rsurface.batchelement3i_bufferoffset = 0;
8296 rsurface.batchelement3s = NULL;
8297 rsurface.batchelement3s_indexbuffer = NULL;
8298 rsurface.batchelement3s_bufferoffset = 0;
8299 if (endvertex <= 65536)
8301 // make a 16bit (unsigned short) index array if possible
8302 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8303 for (i = 0;i < numtriangles*3;i++)
8304 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8310 // something needs software processing, do it for real...
8311 // we only directly handle separate array data in this case and then
8312 // generate interleaved data if needed...
8313 rsurface.batchgeneratedvertex = true;
8315 // now copy the vertex data into a combined array and make an index array
8316 // (this is what Quake3 does all the time)
8317 //if (gaps || rsurface.batchfirstvertex)
8319 rsurface.batchvertex3fbuffer = NULL;
8320 rsurface.batchvertexmesh = NULL;
8321 rsurface.batchvertexmeshbuffer = NULL;
8322 rsurface.batchvertex3f = NULL;
8323 rsurface.batchvertex3f_vertexbuffer = NULL;
8324 rsurface.batchvertex3f_bufferoffset = 0;
8325 rsurface.batchsvector3f = NULL;
8326 rsurface.batchsvector3f_vertexbuffer = NULL;
8327 rsurface.batchsvector3f_bufferoffset = 0;
8328 rsurface.batchtvector3f = NULL;
8329 rsurface.batchtvector3f_vertexbuffer = NULL;
8330 rsurface.batchtvector3f_bufferoffset = 0;
8331 rsurface.batchnormal3f = NULL;
8332 rsurface.batchnormal3f_vertexbuffer = NULL;
8333 rsurface.batchnormal3f_bufferoffset = 0;
8334 rsurface.batchlightmapcolor4f = NULL;
8335 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8336 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8337 rsurface.batchtexcoordtexture2f = NULL;
8338 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8339 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8340 rsurface.batchtexcoordlightmap2f = NULL;
8341 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8342 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8343 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8344 rsurface.batchelement3i_indexbuffer = NULL;
8345 rsurface.batchelement3i_bufferoffset = 0;
8346 rsurface.batchelement3s = NULL;
8347 rsurface.batchelement3s_indexbuffer = NULL;
8348 rsurface.batchelement3s_bufferoffset = 0;
8349 // we'll only be setting up certain arrays as needed
8350 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8351 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8352 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8353 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8354 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8355 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8356 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8358 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8359 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8361 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8362 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8363 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8364 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8365 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8366 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8369 for (i = 0;i < texturenumsurfaces;i++)
8371 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8372 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8373 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8374 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8375 // copy only the data requested
8376 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8377 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8378 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8380 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8381 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8382 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8383 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8384 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8386 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8387 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8389 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8390 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8391 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8392 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8393 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8394 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8396 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8397 numvertices += surfacenumvertices;
8398 numtriangles += surfacenumtriangles;
8401 // generate a 16bit index array as well if possible
8402 // (in general, dynamic batches fit)
8403 if (numvertices <= 65536)
8405 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8406 for (i = 0;i < numtriangles*3;i++)
8407 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8410 // since we've copied everything, the batch now starts at 0
8411 rsurface.batchfirstvertex = 0;
8412 rsurface.batchnumvertices = batchnumvertices;
8413 rsurface.batchfirsttriangle = 0;
8414 rsurface.batchnumtriangles = batchnumtriangles;
8417 // q1bsp surfaces rendered in vertex color mode have to have colors
8418 // calculated based on lightstyles
8419 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8421 // generate color arrays for the surfaces in this list
8426 const unsigned char *lm;
8427 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8428 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8429 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8431 for (i = 0;i < texturenumsurfaces;i++)
8433 surface = texturesurfacelist[i];
8434 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8435 surfacenumvertices = surface->num_vertices;
8436 if (surface->lightmapinfo->samples)
8438 for (j = 0;j < surfacenumvertices;j++)
8440 lm = surface->lightmapinfo->samples + offsets[j];
8441 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8442 VectorScale(lm, scale, c);
8443 if (surface->lightmapinfo->styles[1] != 255)
8445 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8447 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8448 VectorMA(c, scale, lm, c);
8449 if (surface->lightmapinfo->styles[2] != 255)
8452 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8453 VectorMA(c, scale, lm, c);
8454 if (surface->lightmapinfo->styles[3] != 255)
8457 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8458 VectorMA(c, scale, lm, c);
8465 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);
8471 for (j = 0;j < surfacenumvertices;j++)
8473 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8480 // if vertices are deformed (sprite flares and things in maps, possibly
8481 // water waves, bulges and other deformations), modify the copied vertices
8483 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8485 switch (deform->deform)
8488 case Q3DEFORM_PROJECTIONSHADOW:
8489 case Q3DEFORM_TEXT0:
8490 case Q3DEFORM_TEXT1:
8491 case Q3DEFORM_TEXT2:
8492 case Q3DEFORM_TEXT3:
8493 case Q3DEFORM_TEXT4:
8494 case Q3DEFORM_TEXT5:
8495 case Q3DEFORM_TEXT6:
8496 case Q3DEFORM_TEXT7:
8499 case Q3DEFORM_AUTOSPRITE:
8500 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8501 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8502 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8503 VectorNormalize(newforward);
8504 VectorNormalize(newright);
8505 VectorNormalize(newup);
8506 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8507 // rsurface.batchvertex3f_vertexbuffer = NULL;
8508 // rsurface.batchvertex3f_bufferoffset = 0;
8509 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8510 // rsurface.batchsvector3f_vertexbuffer = NULL;
8511 // rsurface.batchsvector3f_bufferoffset = 0;
8512 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8513 // rsurface.batchtvector3f_vertexbuffer = NULL;
8514 // rsurface.batchtvector3f_bufferoffset = 0;
8515 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8516 // rsurface.batchnormal3f_vertexbuffer = NULL;
8517 // rsurface.batchnormal3f_bufferoffset = 0;
8518 // a single autosprite surface can contain multiple sprites...
8519 for (j = 0;j < batchnumvertices - 3;j += 4)
8521 VectorClear(center);
8522 for (i = 0;i < 4;i++)
8523 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8524 VectorScale(center, 0.25f, center);
8525 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8526 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8527 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8528 for (i = 0;i < 4;i++)
8530 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8531 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8534 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8535 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8536 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);
8538 case Q3DEFORM_AUTOSPRITE2:
8539 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8540 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8541 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8542 VectorNormalize(newforward);
8543 VectorNormalize(newright);
8544 VectorNormalize(newup);
8545 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8546 // rsurface.batchvertex3f_vertexbuffer = NULL;
8547 // rsurface.batchvertex3f_bufferoffset = 0;
8549 const float *v1, *v2;
8559 memset(shortest, 0, sizeof(shortest));
8560 // a single autosprite surface can contain multiple sprites...
8561 for (j = 0;j < batchnumvertices - 3;j += 4)
8563 VectorClear(center);
8564 for (i = 0;i < 4;i++)
8565 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8566 VectorScale(center, 0.25f, center);
8567 // find the two shortest edges, then use them to define the
8568 // axis vectors for rotating around the central axis
8569 for (i = 0;i < 6;i++)
8571 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8572 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8573 l = VectorDistance2(v1, v2);
8574 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8576 l += (1.0f / 1024.0f);
8577 if (shortest[0].length2 > l || i == 0)
8579 shortest[1] = shortest[0];
8580 shortest[0].length2 = l;
8581 shortest[0].v1 = v1;
8582 shortest[0].v2 = v2;
8584 else if (shortest[1].length2 > l || i == 1)
8586 shortest[1].length2 = l;
8587 shortest[1].v1 = v1;
8588 shortest[1].v2 = v2;
8591 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8592 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8593 // this calculates the right vector from the shortest edge
8594 // and the up vector from the edge midpoints
8595 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8596 VectorNormalize(right);
8597 VectorSubtract(end, start, up);
8598 VectorNormalize(up);
8599 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8600 VectorSubtract(rsurface.localvieworigin, center, forward);
8601 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8602 VectorNegate(forward, forward);
8603 VectorReflect(forward, 0, up, forward);
8604 VectorNormalize(forward);
8605 CrossProduct(up, forward, newright);
8606 VectorNormalize(newright);
8607 // rotate the quad around the up axis vector, this is made
8608 // especially easy by the fact we know the quad is flat,
8609 // so we only have to subtract the center position and
8610 // measure distance along the right vector, and then
8611 // multiply that by the newright vector and add back the
8613 // we also need to subtract the old position to undo the
8614 // displacement from the center, which we do with a
8615 // DotProduct, the subtraction/addition of center is also
8616 // optimized into DotProducts here
8617 l = DotProduct(right, center);
8618 for (i = 0;i < 4;i++)
8620 v1 = rsurface.batchvertex3f + 3*(j+i);
8621 f = DotProduct(right, v1) - l;
8622 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8626 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8628 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8629 // rsurface.batchnormal3f_vertexbuffer = NULL;
8630 // rsurface.batchnormal3f_bufferoffset = 0;
8631 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8633 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8635 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8636 // rsurface.batchsvector3f_vertexbuffer = NULL;
8637 // rsurface.batchsvector3f_bufferoffset = 0;
8638 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8639 // rsurface.batchtvector3f_vertexbuffer = NULL;
8640 // rsurface.batchtvector3f_bufferoffset = 0;
8641 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);
8644 case Q3DEFORM_NORMAL:
8645 // deform the normals to make reflections wavey
8646 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8647 rsurface.batchnormal3f_vertexbuffer = NULL;
8648 rsurface.batchnormal3f_bufferoffset = 0;
8649 for (j = 0;j < batchnumvertices;j++)
8652 float *normal = rsurface.batchnormal3f + 3*j;
8653 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8654 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8655 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]);
8656 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]);
8657 VectorNormalize(normal);
8659 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8661 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8662 // rsurface.batchsvector3f_vertexbuffer = NULL;
8663 // rsurface.batchsvector3f_bufferoffset = 0;
8664 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8665 // rsurface.batchtvector3f_vertexbuffer = NULL;
8666 // rsurface.batchtvector3f_bufferoffset = 0;
8667 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);
8671 // deform vertex array to make wavey water and flags and such
8672 waveparms[0] = deform->waveparms[0];
8673 waveparms[1] = deform->waveparms[1];
8674 waveparms[2] = deform->waveparms[2];
8675 waveparms[3] = deform->waveparms[3];
8676 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8677 break; // if wavefunc is a nop, don't make a dynamic vertex array
8678 // this is how a divisor of vertex influence on deformation
8679 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8680 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8681 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8682 // rsurface.batchvertex3f_vertexbuffer = NULL;
8683 // rsurface.batchvertex3f_bufferoffset = 0;
8684 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8685 // rsurface.batchnormal3f_vertexbuffer = NULL;
8686 // rsurface.batchnormal3f_bufferoffset = 0;
8687 for (j = 0;j < batchnumvertices;j++)
8689 // if the wavefunc depends on time, evaluate it per-vertex
8692 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8693 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8695 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8697 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8698 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8699 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8701 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8702 // rsurface.batchsvector3f_vertexbuffer = NULL;
8703 // rsurface.batchsvector3f_bufferoffset = 0;
8704 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8705 // rsurface.batchtvector3f_vertexbuffer = NULL;
8706 // rsurface.batchtvector3f_bufferoffset = 0;
8707 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);
8710 case Q3DEFORM_BULGE:
8711 // deform vertex array to make the surface have moving bulges
8712 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8713 // rsurface.batchvertex3f_vertexbuffer = NULL;
8714 // rsurface.batchvertex3f_bufferoffset = 0;
8715 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8716 // rsurface.batchnormal3f_vertexbuffer = NULL;
8717 // rsurface.batchnormal3f_bufferoffset = 0;
8718 for (j = 0;j < batchnumvertices;j++)
8720 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8721 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8723 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8724 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8725 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8727 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8728 // rsurface.batchsvector3f_vertexbuffer = NULL;
8729 // rsurface.batchsvector3f_bufferoffset = 0;
8730 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8731 // rsurface.batchtvector3f_vertexbuffer = NULL;
8732 // rsurface.batchtvector3f_bufferoffset = 0;
8733 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);
8737 // deform vertex array
8738 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8739 break; // if wavefunc is a nop, don't make a dynamic vertex array
8740 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8741 VectorScale(deform->parms, scale, waveparms);
8742 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8743 // rsurface.batchvertex3f_vertexbuffer = NULL;
8744 // rsurface.batchvertex3f_bufferoffset = 0;
8745 for (j = 0;j < batchnumvertices;j++)
8746 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8751 // generate texcoords based on the chosen texcoord source
8752 switch(rsurface.texture->tcgen.tcgen)
8755 case Q3TCGEN_TEXTURE:
8757 case Q3TCGEN_LIGHTMAP:
8758 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8759 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8760 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8761 if (rsurface.batchtexcoordlightmap2f)
8762 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8764 case Q3TCGEN_VECTOR:
8765 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8766 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8767 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8768 for (j = 0;j < batchnumvertices;j++)
8770 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8771 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8774 case Q3TCGEN_ENVIRONMENT:
8775 // make environment reflections using a spheremap
8776 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8777 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8778 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8779 for (j = 0;j < batchnumvertices;j++)
8781 // identical to Q3A's method, but executed in worldspace so
8782 // carried models can be shiny too
8784 float viewer[3], d, reflected[3], worldreflected[3];
8786 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8787 // VectorNormalize(viewer);
8789 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8791 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8792 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8793 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8794 // note: this is proportinal to viewer, so we can normalize later
8796 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8797 VectorNormalize(worldreflected);
8799 // note: this sphere map only uses world x and z!
8800 // so positive and negative y will LOOK THE SAME.
8801 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8802 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8806 // the only tcmod that needs software vertex processing is turbulent, so
8807 // check for it here and apply the changes if needed
8808 // and we only support that as the first one
8809 // (handling a mixture of turbulent and other tcmods would be problematic
8810 // without punting it entirely to a software path)
8811 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8813 amplitude = rsurface.texture->tcmods[0].parms[1];
8814 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8815 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8816 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8817 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8818 for (j = 0;j < batchnumvertices;j++)
8820 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);
8821 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8825 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8827 // convert the modified arrays to vertex structs
8828 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8829 // rsurface.batchvertexmeshbuffer = NULL;
8830 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8831 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8832 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8833 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8834 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8835 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8836 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8838 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8840 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8841 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8844 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8845 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8846 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8847 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8848 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8849 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8850 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8851 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8852 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8856 void RSurf_DrawBatch(void)
8858 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8859 // through the pipeline, killing it earlier in the pipeline would have
8860 // per-surface overhead rather than per-batch overhead, so it's best to
8861 // reject it here, before it hits glDraw.
8862 if (rsurface.batchnumtriangles == 0)
8865 // batch debugging code
8866 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8872 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8873 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8876 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8878 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8880 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8881 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);
8888 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);
8891 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8893 // pick the closest matching water plane
8894 int planeindex, vertexindex, bestplaneindex = -1;
8898 r_waterstate_waterplane_t *p;
8899 qboolean prepared = false;
8901 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8903 if(p->camera_entity != rsurface.texture->camera_entity)
8908 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8910 if(rsurface.batchnumvertices == 0)
8913 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8915 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8916 d += fabs(PlaneDiff(vert, &p->plane));
8918 if (bestd > d || bestplaneindex < 0)
8921 bestplaneindex = planeindex;
8924 return bestplaneindex;
8925 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8926 // this situation though, as it might be better to render single larger
8927 // batches with useless stuff (backface culled for example) than to
8928 // render multiple smaller batches
8931 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8934 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8935 rsurface.passcolor4f_vertexbuffer = 0;
8936 rsurface.passcolor4f_bufferoffset = 0;
8937 for (i = 0;i < rsurface.batchnumvertices;i++)
8938 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8941 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8948 if (rsurface.passcolor4f)
8950 // generate color arrays
8951 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8952 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8953 rsurface.passcolor4f_vertexbuffer = 0;
8954 rsurface.passcolor4f_bufferoffset = 0;
8955 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)
8957 f = RSurf_FogVertex(v);
8966 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8967 rsurface.passcolor4f_vertexbuffer = 0;
8968 rsurface.passcolor4f_bufferoffset = 0;
8969 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8971 f = RSurf_FogVertex(v);
8980 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8987 if (!rsurface.passcolor4f)
8989 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8990 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8991 rsurface.passcolor4f_vertexbuffer = 0;
8992 rsurface.passcolor4f_bufferoffset = 0;
8993 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)
8995 f = RSurf_FogVertex(v);
8996 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8997 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8998 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9003 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9008 if (!rsurface.passcolor4f)
9010 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9011 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9012 rsurface.passcolor4f_vertexbuffer = 0;
9013 rsurface.passcolor4f_bufferoffset = 0;
9014 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9023 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9028 if (!rsurface.passcolor4f)
9030 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9031 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9032 rsurface.passcolor4f_vertexbuffer = 0;
9033 rsurface.passcolor4f_bufferoffset = 0;
9034 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9036 c2[0] = c[0] + r_refdef.scene.ambient;
9037 c2[1] = c[1] + r_refdef.scene.ambient;
9038 c2[2] = c[2] + r_refdef.scene.ambient;
9043 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9046 rsurface.passcolor4f = NULL;
9047 rsurface.passcolor4f_vertexbuffer = 0;
9048 rsurface.passcolor4f_bufferoffset = 0;
9049 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9050 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9051 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9052 GL_Color(r, g, b, a);
9053 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9057 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9059 // TODO: optimize applyfog && applycolor case
9060 // just apply fog if necessary, and tint the fog color array if necessary
9061 rsurface.passcolor4f = NULL;
9062 rsurface.passcolor4f_vertexbuffer = 0;
9063 rsurface.passcolor4f_bufferoffset = 0;
9064 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9065 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9066 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9067 GL_Color(r, g, b, a);
9071 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9074 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9075 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9076 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9077 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9078 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9079 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9080 GL_Color(r, g, b, a);
9084 static void RSurf_DrawBatch_GL11_ClampColor(void)
9089 if (!rsurface.passcolor4f)
9091 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9093 c2[0] = bound(0.0f, c1[0], 1.0f);
9094 c2[1] = bound(0.0f, c1[1], 1.0f);
9095 c2[2] = bound(0.0f, c1[2], 1.0f);
9096 c2[3] = bound(0.0f, c1[3], 1.0f);
9100 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9110 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9111 rsurface.passcolor4f_vertexbuffer = 0;
9112 rsurface.passcolor4f_bufferoffset = 0;
9113 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)
9115 f = -DotProduct(r_refdef.view.forward, n);
9117 f = f * 0.85 + 0.15; // work around so stuff won't get black
9118 f *= r_refdef.lightmapintensity;
9119 Vector4Set(c, f, f, f, 1);
9123 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9125 RSurf_DrawBatch_GL11_ApplyFakeLight();
9126 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9127 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9128 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9129 GL_Color(r, g, b, a);
9133 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9141 vec3_t ambientcolor;
9142 vec3_t diffusecolor;
9146 VectorCopy(rsurface.modellight_lightdir, lightdir);
9147 f = 0.5f * r_refdef.lightmapintensity;
9148 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9149 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9150 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9151 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9152 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9153 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9155 if (VectorLength2(diffusecolor) > 0)
9157 // q3-style directional shading
9158 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9159 rsurface.passcolor4f_vertexbuffer = 0;
9160 rsurface.passcolor4f_bufferoffset = 0;
9161 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)
9163 if ((f = DotProduct(n, lightdir)) > 0)
9164 VectorMA(ambientcolor, f, diffusecolor, c);
9166 VectorCopy(ambientcolor, c);
9173 *applycolor = false;
9177 *r = ambientcolor[0];
9178 *g = ambientcolor[1];
9179 *b = ambientcolor[2];
9180 rsurface.passcolor4f = NULL;
9181 rsurface.passcolor4f_vertexbuffer = 0;
9182 rsurface.passcolor4f_bufferoffset = 0;
9186 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9188 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9189 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9190 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9191 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9192 GL_Color(r, g, b, a);
9196 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9202 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9204 f = 1 - RSurf_FogVertex(v);
9212 void RSurf_SetupDepthAndCulling(void)
9214 // submodels are biased to avoid z-fighting with world surfaces that they
9215 // may be exactly overlapping (avoids z-fighting artifacts on certain
9216 // doors and things in Quake maps)
9217 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9218 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9219 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9220 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9223 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9225 // transparent sky would be ridiculous
9226 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9228 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9229 skyrenderlater = true;
9230 RSurf_SetupDepthAndCulling();
9232 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9233 // skymasking on them, and Quake3 never did sky masking (unlike
9234 // software Quake and software Quake2), so disable the sky masking
9235 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9236 // and skymasking also looks very bad when noclipping outside the
9237 // level, so don't use it then either.
9238 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9240 R_Mesh_ResetTextureState();
9241 if (skyrendermasked)
9243 R_SetupShader_DepthOrShadow();
9244 // depth-only (masking)
9245 GL_ColorMask(0,0,0,0);
9246 // just to make sure that braindead drivers don't draw
9247 // anything despite that colormask...
9248 GL_BlendFunc(GL_ZERO, GL_ONE);
9249 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9250 if (rsurface.batchvertex3fbuffer)
9251 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9253 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9257 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9259 GL_BlendFunc(GL_ONE, GL_ZERO);
9260 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9261 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9262 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9265 if (skyrendermasked)
9266 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9268 R_Mesh_ResetTextureState();
9269 GL_Color(1, 1, 1, 1);
9272 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9273 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9274 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9276 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9280 // render screenspace normalmap to texture
9282 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9287 // bind lightmap texture
9289 // water/refraction/reflection/camera surfaces have to be handled specially
9290 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9292 int start, end, startplaneindex;
9293 for (start = 0;start < texturenumsurfaces;start = end)
9295 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9296 if(startplaneindex < 0)
9298 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9299 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9303 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9305 // now that we have a batch using the same planeindex, render it
9306 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9308 // render water or distortion background
9310 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));
9312 // blend surface on top
9313 GL_DepthMask(false);
9314 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9317 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9319 // render surface with reflection texture as input
9320 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9321 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));
9328 // render surface batch normally
9329 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9330 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9334 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9336 // OpenGL 1.3 path - anything not completely ancient
9337 qboolean applycolor;
9340 const texturelayer_t *layer;
9341 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);
9342 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9344 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9347 int layertexrgbscale;
9348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9350 if (layerindex == 0)
9354 GL_AlphaTest(false);
9355 GL_DepthFunc(GL_EQUAL);
9358 GL_DepthMask(layer->depthmask && writedepth);
9359 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9360 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9362 layertexrgbscale = 4;
9363 VectorScale(layer->color, 0.25f, layercolor);
9365 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9367 layertexrgbscale = 2;
9368 VectorScale(layer->color, 0.5f, layercolor);
9372 layertexrgbscale = 1;
9373 VectorScale(layer->color, 1.0f, layercolor);
9375 layercolor[3] = layer->color[3];
9376 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9377 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9378 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9379 switch (layer->type)
9381 case TEXTURELAYERTYPE_LITTEXTURE:
9382 // single-pass lightmapped texture with 2x rgbscale
9383 R_Mesh_TexBind(0, r_texture_white);
9384 R_Mesh_TexMatrix(0, NULL);
9385 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9386 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9387 R_Mesh_TexBind(1, layer->texture);
9388 R_Mesh_TexMatrix(1, &layer->texmatrix);
9389 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9390 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9391 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9392 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9393 else if (FAKELIGHT_ENABLED)
9394 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9395 else if (rsurface.uselightmaptexture)
9396 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9398 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9400 case TEXTURELAYERTYPE_TEXTURE:
9401 // singletexture unlit texture with transparency support
9402 R_Mesh_TexBind(0, layer->texture);
9403 R_Mesh_TexMatrix(0, &layer->texmatrix);
9404 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9405 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9406 R_Mesh_TexBind(1, 0);
9407 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9408 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9410 case TEXTURELAYERTYPE_FOG:
9411 // singletexture fogging
9414 R_Mesh_TexBind(0, layer->texture);
9415 R_Mesh_TexMatrix(0, &layer->texmatrix);
9416 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9417 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9421 R_Mesh_TexBind(0, 0);
9422 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9424 R_Mesh_TexBind(1, 0);
9425 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9426 // generate a color array for the fog pass
9427 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9428 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9432 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9435 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9437 GL_DepthFunc(GL_LEQUAL);
9438 GL_AlphaTest(false);
9442 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9444 // OpenGL 1.1 - crusty old voodoo path
9447 const texturelayer_t *layer;
9448 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);
9449 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9451 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9453 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9455 if (layerindex == 0)
9459 GL_AlphaTest(false);
9460 GL_DepthFunc(GL_EQUAL);
9463 GL_DepthMask(layer->depthmask && writedepth);
9464 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9465 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9466 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9467 switch (layer->type)
9469 case TEXTURELAYERTYPE_LITTEXTURE:
9470 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9472 // two-pass lit texture with 2x rgbscale
9473 // first the lightmap pass
9474 R_Mesh_TexBind(0, r_texture_white);
9475 R_Mesh_TexMatrix(0, NULL);
9476 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9477 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9478 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9479 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9480 else if (FAKELIGHT_ENABLED)
9481 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9482 else if (rsurface.uselightmaptexture)
9483 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9485 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9486 // then apply the texture to it
9487 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9488 R_Mesh_TexBind(0, layer->texture);
9489 R_Mesh_TexMatrix(0, &layer->texmatrix);
9490 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9491 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9492 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);
9496 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9497 R_Mesh_TexBind(0, layer->texture);
9498 R_Mesh_TexMatrix(0, &layer->texmatrix);
9499 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9500 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9501 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9502 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);
9504 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);
9507 case TEXTURELAYERTYPE_TEXTURE:
9508 // singletexture unlit texture with transparency support
9509 R_Mesh_TexBind(0, layer->texture);
9510 R_Mesh_TexMatrix(0, &layer->texmatrix);
9511 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9512 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9513 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);
9515 case TEXTURELAYERTYPE_FOG:
9516 // singletexture fogging
9519 R_Mesh_TexBind(0, layer->texture);
9520 R_Mesh_TexMatrix(0, &layer->texmatrix);
9521 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9522 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9526 R_Mesh_TexBind(0, 0);
9527 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9529 // generate a color array for the fog pass
9530 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9531 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9535 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9538 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9540 GL_DepthFunc(GL_LEQUAL);
9541 GL_AlphaTest(false);
9545 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9549 r_vertexgeneric_t *batchvertex;
9552 // R_Mesh_ResetTextureState();
9553 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9555 if(rsurface.texture && rsurface.texture->currentskinframe)
9557 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9558 c[3] *= rsurface.texture->currentalpha;
9568 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9570 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9571 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9572 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9575 // brighten it up (as texture value 127 means "unlit")
9576 c[0] *= 2 * r_refdef.view.colorscale;
9577 c[1] *= 2 * r_refdef.view.colorscale;
9578 c[2] *= 2 * r_refdef.view.colorscale;
9580 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9581 c[3] *= r_wateralpha.value;
9583 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9585 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9586 GL_DepthMask(false);
9588 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9590 GL_BlendFunc(GL_ONE, GL_ONE);
9591 GL_DepthMask(false);
9593 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9595 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9596 GL_DepthMask(false);
9598 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9600 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9601 GL_DepthMask(false);
9605 GL_BlendFunc(GL_ONE, GL_ZERO);
9606 GL_DepthMask(writedepth);
9609 if (r_showsurfaces.integer == 3)
9611 rsurface.passcolor4f = NULL;
9613 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9615 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9617 rsurface.passcolor4f = NULL;
9618 rsurface.passcolor4f_vertexbuffer = 0;
9619 rsurface.passcolor4f_bufferoffset = 0;
9621 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9623 qboolean applycolor = true;
9626 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9628 r_refdef.lightmapintensity = 1;
9629 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9630 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9632 else if (FAKELIGHT_ENABLED)
9634 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9636 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9637 RSurf_DrawBatch_GL11_ApplyFakeLight();
9638 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9642 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9644 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9645 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9646 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9649 if(!rsurface.passcolor4f)
9650 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9652 RSurf_DrawBatch_GL11_ApplyAmbient();
9653 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9654 if(r_refdef.fogenabled)
9655 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9656 RSurf_DrawBatch_GL11_ClampColor();
9658 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9659 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9662 else if (!r_refdef.view.showdebug)
9664 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9665 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9666 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9668 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9669 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9671 R_Mesh_PrepareVertices_Generic_Unlock();
9674 else if (r_showsurfaces.integer == 4)
9676 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9677 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9678 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9680 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9681 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9682 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9684 R_Mesh_PrepareVertices_Generic_Unlock();
9687 else if (r_showsurfaces.integer == 2)
9690 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9691 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9692 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9694 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9695 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9696 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9697 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9698 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9699 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9700 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9702 R_Mesh_PrepareVertices_Generic_Unlock();
9703 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9707 int texturesurfaceindex;
9709 const msurface_t *surface;
9710 float surfacecolor4f[4];
9711 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9712 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9714 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9716 surface = texturesurfacelist[texturesurfaceindex];
9717 k = (int)(((size_t)surface) / sizeof(msurface_t));
9718 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9719 for (j = 0;j < surface->num_vertices;j++)
9721 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9722 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9726 R_Mesh_PrepareVertices_Generic_Unlock();
9731 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9734 RSurf_SetupDepthAndCulling();
9735 if (r_showsurfaces.integer)
9737 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9740 switch (vid.renderpath)
9742 case RENDERPATH_GL20:
9743 case RENDERPATH_D3D9:
9744 case RENDERPATH_D3D10:
9745 case RENDERPATH_D3D11:
9746 case RENDERPATH_SOFT:
9747 case RENDERPATH_GLES2:
9748 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9750 case RENDERPATH_GL13:
9751 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9753 case RENDERPATH_GL11:
9754 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9760 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9763 RSurf_SetupDepthAndCulling();
9764 if (r_showsurfaces.integer)
9766 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9769 switch (vid.renderpath)
9771 case RENDERPATH_GL20:
9772 case RENDERPATH_D3D9:
9773 case RENDERPATH_D3D10:
9774 case RENDERPATH_D3D11:
9775 case RENDERPATH_SOFT:
9776 case RENDERPATH_GLES2:
9777 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9779 case RENDERPATH_GL13:
9780 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9782 case RENDERPATH_GL11:
9783 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9789 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9792 int texturenumsurfaces, endsurface;
9794 const msurface_t *surface;
9795 #define MAXBATCH_TRANSPARENTSURFACES 256
9796 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9798 // if the model is static it doesn't matter what value we give for
9799 // wantnormals and wanttangents, so this logic uses only rules applicable
9800 // to a model, knowing that they are meaningless otherwise
9801 if (ent == r_refdef.scene.worldentity)
9802 RSurf_ActiveWorldEntity();
9803 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9804 RSurf_ActiveModelEntity(ent, false, false, false);
9807 switch (vid.renderpath)
9809 case RENDERPATH_GL20:
9810 case RENDERPATH_D3D9:
9811 case RENDERPATH_D3D10:
9812 case RENDERPATH_D3D11:
9813 case RENDERPATH_SOFT:
9814 case RENDERPATH_GLES2:
9815 RSurf_ActiveModelEntity(ent, true, true, false);
9817 case RENDERPATH_GL13:
9818 case RENDERPATH_GL11:
9819 RSurf_ActiveModelEntity(ent, true, false, false);
9824 if (r_transparentdepthmasking.integer)
9826 qboolean setup = false;
9827 for (i = 0;i < numsurfaces;i = j)
9830 surface = rsurface.modelsurfaces + surfacelist[i];
9831 texture = surface->texture;
9832 rsurface.texture = R_GetCurrentTexture(texture);
9833 rsurface.lightmaptexture = NULL;
9834 rsurface.deluxemaptexture = NULL;
9835 rsurface.uselightmaptexture = false;
9836 // scan ahead until we find a different texture
9837 endsurface = min(i + 1024, numsurfaces);
9838 texturenumsurfaces = 0;
9839 texturesurfacelist[texturenumsurfaces++] = surface;
9840 for (;j < endsurface;j++)
9842 surface = rsurface.modelsurfaces + surfacelist[j];
9843 if (texture != surface->texture)
9845 texturesurfacelist[texturenumsurfaces++] = surface;
9847 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9849 // render the range of surfaces as depth
9853 GL_ColorMask(0,0,0,0);
9856 GL_BlendFunc(GL_ONE, GL_ZERO);
9858 // R_Mesh_ResetTextureState();
9859 R_SetupShader_DepthOrShadow();
9861 RSurf_SetupDepthAndCulling();
9862 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9863 if (rsurface.batchvertex3fbuffer)
9864 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9866 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9870 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9873 for (i = 0;i < numsurfaces;i = j)
9876 surface = rsurface.modelsurfaces + surfacelist[i];
9877 texture = surface->texture;
9878 rsurface.texture = R_GetCurrentTexture(texture);
9879 // scan ahead until we find a different texture
9880 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9881 texturenumsurfaces = 0;
9882 texturesurfacelist[texturenumsurfaces++] = surface;
9883 if(FAKELIGHT_ENABLED)
9885 rsurface.lightmaptexture = NULL;
9886 rsurface.deluxemaptexture = NULL;
9887 rsurface.uselightmaptexture = false;
9888 for (;j < endsurface;j++)
9890 surface = rsurface.modelsurfaces + surfacelist[j];
9891 if (texture != surface->texture)
9893 texturesurfacelist[texturenumsurfaces++] = surface;
9898 rsurface.lightmaptexture = surface->lightmaptexture;
9899 rsurface.deluxemaptexture = surface->deluxemaptexture;
9900 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9901 for (;j < endsurface;j++)
9903 surface = rsurface.modelsurfaces + surfacelist[j];
9904 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9906 texturesurfacelist[texturenumsurfaces++] = surface;
9909 // render the range of surfaces
9910 if (ent == r_refdef.scene.worldentity)
9911 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9913 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9915 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9918 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9920 // transparent surfaces get pushed off into the transparent queue
9921 int surfacelistindex;
9922 const msurface_t *surface;
9923 vec3_t tempcenter, center;
9924 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9926 surface = texturesurfacelist[surfacelistindex];
9927 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9928 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9929 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9930 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9931 if (queueentity->transparent_offset) // transparent offset
9933 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9934 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9935 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9937 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9941 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9943 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9945 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9947 RSurf_SetupDepthAndCulling();
9948 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9949 if (rsurface.batchvertex3fbuffer)
9950 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9952 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9956 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9958 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9961 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9964 if (!rsurface.texture->currentnumlayers)
9966 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9967 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9969 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9971 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9972 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9973 else if (!rsurface.texture->currentnumlayers)
9975 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9977 // in the deferred case, transparent surfaces were queued during prepass
9978 if (!r_shadow_usingdeferredprepass)
9979 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9983 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9984 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9989 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9993 R_FrameData_SetMark();
9994 // break the surface list down into batches by texture and use of lightmapping
9995 for (i = 0;i < numsurfaces;i = j)
9998 // texture is the base texture pointer, rsurface.texture is the
9999 // current frame/skin the texture is directing us to use (for example
10000 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10001 // use skin 1 instead)
10002 texture = surfacelist[i]->texture;
10003 rsurface.texture = R_GetCurrentTexture(texture);
10004 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10006 // if this texture is not the kind we want, skip ahead to the next one
10007 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10011 if(FAKELIGHT_ENABLED || depthonly || prepass)
10013 rsurface.lightmaptexture = NULL;
10014 rsurface.deluxemaptexture = NULL;
10015 rsurface.uselightmaptexture = false;
10016 // simply scan ahead until we find a different texture or lightmap state
10017 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10022 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10023 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10024 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10025 // simply scan ahead until we find a different texture or lightmap state
10026 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10029 // render the range of surfaces
10030 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10032 R_FrameData_ReturnToMark();
10035 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10039 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10042 if (!rsurface.texture->currentnumlayers)
10044 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10045 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10047 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10049 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10050 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10051 else if (!rsurface.texture->currentnumlayers)
10053 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10055 // in the deferred case, transparent surfaces were queued during prepass
10056 if (!r_shadow_usingdeferredprepass)
10057 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10061 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10062 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10067 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10070 texture_t *texture;
10071 R_FrameData_SetMark();
10072 // break the surface list down into batches by texture and use of lightmapping
10073 for (i = 0;i < numsurfaces;i = j)
10076 // texture is the base texture pointer, rsurface.texture is the
10077 // current frame/skin the texture is directing us to use (for example
10078 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10079 // use skin 1 instead)
10080 texture = surfacelist[i]->texture;
10081 rsurface.texture = R_GetCurrentTexture(texture);
10082 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10084 // if this texture is not the kind we want, skip ahead to the next one
10085 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10089 if(FAKELIGHT_ENABLED || depthonly || prepass)
10091 rsurface.lightmaptexture = NULL;
10092 rsurface.deluxemaptexture = NULL;
10093 rsurface.uselightmaptexture = false;
10094 // simply scan ahead until we find a different texture or lightmap state
10095 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10100 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10101 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10102 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10103 // simply scan ahead until we find a different texture or lightmap state
10104 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10107 // render the range of surfaces
10108 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10110 R_FrameData_ReturnToMark();
10113 float locboxvertex3f[6*4*3] =
10115 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10116 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10117 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10118 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10119 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10120 1,0,0, 0,0,0, 0,1,0, 1,1,0
10123 unsigned short locboxelements[6*2*3] =
10128 12,13,14, 12,14,15,
10129 16,17,18, 16,18,19,
10133 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10136 cl_locnode_t *loc = (cl_locnode_t *)ent;
10138 float vertex3f[6*4*3];
10140 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10141 GL_DepthMask(false);
10142 GL_DepthRange(0, 1);
10143 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10144 GL_DepthTest(true);
10145 GL_CullFace(GL_NONE);
10146 R_EntityMatrix(&identitymatrix);
10148 // R_Mesh_ResetTextureState();
10150 i = surfacelist[0];
10151 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10152 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10153 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10154 surfacelist[0] < 0 ? 0.5f : 0.125f);
10156 if (VectorCompare(loc->mins, loc->maxs))
10158 VectorSet(size, 2, 2, 2);
10159 VectorMA(loc->mins, -0.5f, size, mins);
10163 VectorCopy(loc->mins, mins);
10164 VectorSubtract(loc->maxs, loc->mins, size);
10167 for (i = 0;i < 6*4*3;)
10168 for (j = 0;j < 3;j++, i++)
10169 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10171 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10172 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10173 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10176 void R_DrawLocs(void)
10179 cl_locnode_t *loc, *nearestloc;
10181 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10182 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10184 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10185 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10189 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10191 if (decalsystem->decals)
10192 Mem_Free(decalsystem->decals);
10193 memset(decalsystem, 0, sizeof(*decalsystem));
10196 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)
10199 tridecal_t *decals;
10202 // expand or initialize the system
10203 if (decalsystem->maxdecals <= decalsystem->numdecals)
10205 decalsystem_t old = *decalsystem;
10206 qboolean useshortelements;
10207 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10208 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10209 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)));
10210 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10211 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10212 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10213 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10214 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10215 if (decalsystem->numdecals)
10216 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10218 Mem_Free(old.decals);
10219 for (i = 0;i < decalsystem->maxdecals*3;i++)
10220 decalsystem->element3i[i] = i;
10221 if (useshortelements)
10222 for (i = 0;i < decalsystem->maxdecals*3;i++)
10223 decalsystem->element3s[i] = i;
10226 // grab a decal and search for another free slot for the next one
10227 decals = decalsystem->decals;
10228 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10229 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10231 decalsystem->freedecal = i;
10232 if (decalsystem->numdecals <= i)
10233 decalsystem->numdecals = i + 1;
10235 // initialize the decal
10237 decal->triangleindex = triangleindex;
10238 decal->surfaceindex = surfaceindex;
10239 decal->decalsequence = decalsequence;
10240 decal->color4f[0][0] = c0[0];
10241 decal->color4f[0][1] = c0[1];
10242 decal->color4f[0][2] = c0[2];
10243 decal->color4f[0][3] = 1;
10244 decal->color4f[1][0] = c1[0];
10245 decal->color4f[1][1] = c1[1];
10246 decal->color4f[1][2] = c1[2];
10247 decal->color4f[1][3] = 1;
10248 decal->color4f[2][0] = c2[0];
10249 decal->color4f[2][1] = c2[1];
10250 decal->color4f[2][2] = c2[2];
10251 decal->color4f[2][3] = 1;
10252 decal->vertex3f[0][0] = v0[0];
10253 decal->vertex3f[0][1] = v0[1];
10254 decal->vertex3f[0][2] = v0[2];
10255 decal->vertex3f[1][0] = v1[0];
10256 decal->vertex3f[1][1] = v1[1];
10257 decal->vertex3f[1][2] = v1[2];
10258 decal->vertex3f[2][0] = v2[0];
10259 decal->vertex3f[2][1] = v2[1];
10260 decal->vertex3f[2][2] = v2[2];
10261 decal->texcoord2f[0][0] = t0[0];
10262 decal->texcoord2f[0][1] = t0[1];
10263 decal->texcoord2f[1][0] = t1[0];
10264 decal->texcoord2f[1][1] = t1[1];
10265 decal->texcoord2f[2][0] = t2[0];
10266 decal->texcoord2f[2][1] = t2[1];
10269 extern cvar_t cl_decals_bias;
10270 extern cvar_t cl_decals_models;
10271 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10272 // baseparms, parms, temps
10273 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)
10278 const float *vertex3f;
10279 const float *normal3f;
10281 float points[2][9][3];
10288 e = rsurface.modelelement3i + 3*triangleindex;
10290 vertex3f = rsurface.modelvertex3f;
10291 normal3f = rsurface.modelnormal3f;
10295 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10297 index = 3*e[cornerindex];
10298 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10303 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10305 index = 3*e[cornerindex];
10306 VectorCopy(vertex3f + index, v[cornerindex]);
10311 //TriangleNormal(v[0], v[1], v[2], normal);
10312 //if (DotProduct(normal, localnormal) < 0.0f)
10314 // clip by each of the box planes formed from the projection matrix
10315 // if anything survives, we emit the decal
10316 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]);
10319 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]);
10322 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]);
10325 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]);
10328 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]);
10331 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]);
10334 // some part of the triangle survived, so we have to accept it...
10337 // dynamic always uses the original triangle
10339 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10341 index = 3*e[cornerindex];
10342 VectorCopy(vertex3f + index, v[cornerindex]);
10345 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10347 // convert vertex positions to texcoords
10348 Matrix4x4_Transform(projection, v[cornerindex], temp);
10349 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10350 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10351 // calculate distance fade from the projection origin
10352 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10353 f = bound(0.0f, f, 1.0f);
10354 c[cornerindex][0] = r * f;
10355 c[cornerindex][1] = g * f;
10356 c[cornerindex][2] = b * f;
10357 c[cornerindex][3] = 1.0f;
10358 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10361 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);
10363 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10364 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);
10366 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)
10368 matrix4x4_t projection;
10369 decalsystem_t *decalsystem;
10372 const msurface_t *surface;
10373 const msurface_t *surfaces;
10374 const int *surfacelist;
10375 const texture_t *texture;
10377 int numsurfacelist;
10378 int surfacelistindex;
10381 float localorigin[3];
10382 float localnormal[3];
10383 float localmins[3];
10384 float localmaxs[3];
10387 float planes[6][4];
10390 int bih_triangles_count;
10391 int bih_triangles[256];
10392 int bih_surfaces[256];
10394 decalsystem = &ent->decalsystem;
10395 model = ent->model;
10396 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10398 R_DecalSystem_Reset(&ent->decalsystem);
10402 if (!model->brush.data_leafs && !cl_decals_models.integer)
10404 if (decalsystem->model)
10405 R_DecalSystem_Reset(decalsystem);
10409 if (decalsystem->model != model)
10410 R_DecalSystem_Reset(decalsystem);
10411 decalsystem->model = model;
10413 RSurf_ActiveModelEntity(ent, true, false, false);
10415 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10416 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10417 VectorNormalize(localnormal);
10418 localsize = worldsize*rsurface.inversematrixscale;
10419 localmins[0] = localorigin[0] - localsize;
10420 localmins[1] = localorigin[1] - localsize;
10421 localmins[2] = localorigin[2] - localsize;
10422 localmaxs[0] = localorigin[0] + localsize;
10423 localmaxs[1] = localorigin[1] + localsize;
10424 localmaxs[2] = localorigin[2] + localsize;
10426 //VectorCopy(localnormal, planes[4]);
10427 //VectorVectors(planes[4], planes[2], planes[0]);
10428 AnglesFromVectors(angles, localnormal, NULL, false);
10429 AngleVectors(angles, planes[0], planes[2], planes[4]);
10430 VectorNegate(planes[0], planes[1]);
10431 VectorNegate(planes[2], planes[3]);
10432 VectorNegate(planes[4], planes[5]);
10433 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10434 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10435 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10436 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10437 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10438 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10443 matrix4x4_t forwardprojection;
10444 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10445 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10450 float projectionvector[4][3];
10451 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10452 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10453 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10454 projectionvector[0][0] = planes[0][0] * ilocalsize;
10455 projectionvector[0][1] = planes[1][0] * ilocalsize;
10456 projectionvector[0][2] = planes[2][0] * ilocalsize;
10457 projectionvector[1][0] = planes[0][1] * ilocalsize;
10458 projectionvector[1][1] = planes[1][1] * ilocalsize;
10459 projectionvector[1][2] = planes[2][1] * ilocalsize;
10460 projectionvector[2][0] = planes[0][2] * ilocalsize;
10461 projectionvector[2][1] = planes[1][2] * ilocalsize;
10462 projectionvector[2][2] = planes[2][2] * ilocalsize;
10463 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10464 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10465 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10466 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10470 dynamic = model->surfmesh.isanimated;
10471 numsurfacelist = model->nummodelsurfaces;
10472 surfacelist = model->sortedmodelsurfaces;
10473 surfaces = model->data_surfaces;
10476 bih_triangles_count = -1;
10479 if(model->render_bih.numleafs)
10480 bih = &model->render_bih;
10481 else if(model->collision_bih.numleafs)
10482 bih = &model->collision_bih;
10485 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10486 if(bih_triangles_count == 0)
10488 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10490 if(bih_triangles_count > 0)
10492 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10494 surfaceindex = bih_surfaces[triangleindex];
10495 surface = surfaces + surfaceindex;
10496 texture = surface->texture;
10497 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10499 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10501 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10506 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10508 surfaceindex = surfacelist[surfacelistindex];
10509 surface = surfaces + surfaceindex;
10510 // check cull box first because it rejects more than any other check
10511 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10513 // skip transparent surfaces
10514 texture = surface->texture;
10515 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10517 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10519 numtriangles = surface->num_triangles;
10520 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10521 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10526 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10527 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)
10529 int renderentityindex;
10530 float worldmins[3];
10531 float worldmaxs[3];
10532 entity_render_t *ent;
10534 if (!cl_decals_newsystem.integer)
10537 worldmins[0] = worldorigin[0] - worldsize;
10538 worldmins[1] = worldorigin[1] - worldsize;
10539 worldmins[2] = worldorigin[2] - worldsize;
10540 worldmaxs[0] = worldorigin[0] + worldsize;
10541 worldmaxs[1] = worldorigin[1] + worldsize;
10542 worldmaxs[2] = worldorigin[2] + worldsize;
10544 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10546 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10548 ent = r_refdef.scene.entities[renderentityindex];
10549 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10552 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10556 typedef struct r_decalsystem_splatqueue_s
10558 vec3_t worldorigin;
10559 vec3_t worldnormal;
10565 r_decalsystem_splatqueue_t;
10567 int r_decalsystem_numqueued = 0;
10568 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10570 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)
10572 r_decalsystem_splatqueue_t *queue;
10574 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10577 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10578 VectorCopy(worldorigin, queue->worldorigin);
10579 VectorCopy(worldnormal, queue->worldnormal);
10580 Vector4Set(queue->color, r, g, b, a);
10581 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10582 queue->worldsize = worldsize;
10583 queue->decalsequence = cl.decalsequence++;
10586 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10589 r_decalsystem_splatqueue_t *queue;
10591 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10592 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);
10593 r_decalsystem_numqueued = 0;
10596 extern cvar_t cl_decals_max;
10597 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10600 decalsystem_t *decalsystem = &ent->decalsystem;
10607 if (!decalsystem->numdecals)
10610 if (r_showsurfaces.integer)
10613 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10615 R_DecalSystem_Reset(decalsystem);
10619 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10620 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10622 if (decalsystem->lastupdatetime)
10623 frametime = (cl.time - decalsystem->lastupdatetime);
10626 decalsystem->lastupdatetime = cl.time;
10627 decal = decalsystem->decals;
10628 numdecals = decalsystem->numdecals;
10630 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10632 if (decal->color4f[0][3])
10634 decal->lived += frametime;
10635 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10637 memset(decal, 0, sizeof(*decal));
10638 if (decalsystem->freedecal > i)
10639 decalsystem->freedecal = i;
10643 decal = decalsystem->decals;
10644 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10647 // collapse the array by shuffling the tail decals into the gaps
10650 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10651 decalsystem->freedecal++;
10652 if (decalsystem->freedecal == numdecals)
10654 decal[decalsystem->freedecal] = decal[--numdecals];
10657 decalsystem->numdecals = numdecals;
10659 if (numdecals <= 0)
10661 // if there are no decals left, reset decalsystem
10662 R_DecalSystem_Reset(decalsystem);
10666 extern skinframe_t *decalskinframe;
10667 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10670 decalsystem_t *decalsystem = &ent->decalsystem;
10679 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10682 numdecals = decalsystem->numdecals;
10686 if (r_showsurfaces.integer)
10689 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10691 R_DecalSystem_Reset(decalsystem);
10695 // if the model is static it doesn't matter what value we give for
10696 // wantnormals and wanttangents, so this logic uses only rules applicable
10697 // to a model, knowing that they are meaningless otherwise
10698 if (ent == r_refdef.scene.worldentity)
10699 RSurf_ActiveWorldEntity();
10701 RSurf_ActiveModelEntity(ent, false, false, false);
10703 decalsystem->lastupdatetime = cl.time;
10704 decal = decalsystem->decals;
10706 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10708 // update vertex positions for animated models
10709 v3f = decalsystem->vertex3f;
10710 c4f = decalsystem->color4f;
10711 t2f = decalsystem->texcoord2f;
10712 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10714 if (!decal->color4f[0][3])
10717 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10720 // update color values for fading decals
10721 if (decal->lived >= cl_decals_time.value)
10722 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10726 c4f[ 0] = decal->color4f[0][0] * alpha;
10727 c4f[ 1] = decal->color4f[0][1] * alpha;
10728 c4f[ 2] = decal->color4f[0][2] * alpha;
10730 c4f[ 4] = decal->color4f[1][0] * alpha;
10731 c4f[ 5] = decal->color4f[1][1] * alpha;
10732 c4f[ 6] = decal->color4f[1][2] * alpha;
10734 c4f[ 8] = decal->color4f[2][0] * alpha;
10735 c4f[ 9] = decal->color4f[2][1] * alpha;
10736 c4f[10] = decal->color4f[2][2] * alpha;
10739 t2f[0] = decal->texcoord2f[0][0];
10740 t2f[1] = decal->texcoord2f[0][1];
10741 t2f[2] = decal->texcoord2f[1][0];
10742 t2f[3] = decal->texcoord2f[1][1];
10743 t2f[4] = decal->texcoord2f[2][0];
10744 t2f[5] = decal->texcoord2f[2][1];
10746 // update vertex positions for animated models
10747 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10749 e = rsurface.modelelement3i + 3*decal->triangleindex;
10750 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10751 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10752 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10756 VectorCopy(decal->vertex3f[0], v3f);
10757 VectorCopy(decal->vertex3f[1], v3f + 3);
10758 VectorCopy(decal->vertex3f[2], v3f + 6);
10761 if (r_refdef.fogenabled)
10763 alpha = RSurf_FogVertex(v3f);
10764 VectorScale(c4f, alpha, c4f);
10765 alpha = RSurf_FogVertex(v3f + 3);
10766 VectorScale(c4f + 4, alpha, c4f + 4);
10767 alpha = RSurf_FogVertex(v3f + 6);
10768 VectorScale(c4f + 8, alpha, c4f + 8);
10779 r_refdef.stats.drawndecals += numtris;
10781 // now render the decals all at once
10782 // (this assumes they all use one particle font texture!)
10783 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);
10784 // R_Mesh_ResetTextureState();
10785 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10786 GL_DepthMask(false);
10787 GL_DepthRange(0, 1);
10788 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10789 GL_DepthTest(true);
10790 GL_CullFace(GL_NONE);
10791 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10792 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10793 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10797 static void R_DrawModelDecals(void)
10801 // fade faster when there are too many decals
10802 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10803 for (i = 0;i < r_refdef.scene.numentities;i++)
10804 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10806 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10807 for (i = 0;i < r_refdef.scene.numentities;i++)
10808 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10809 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10811 R_DecalSystem_ApplySplatEntitiesQueue();
10813 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10814 for (i = 0;i < r_refdef.scene.numentities;i++)
10815 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10817 r_refdef.stats.totaldecals += numdecals;
10819 if (r_showsurfaces.integer)
10822 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10824 for (i = 0;i < r_refdef.scene.numentities;i++)
10826 if (!r_refdef.viewcache.entityvisible[i])
10828 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10829 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10833 extern cvar_t mod_collision_bih;
10834 void R_DrawDebugModel(void)
10836 entity_render_t *ent = rsurface.entity;
10837 int i, j, k, l, flagsmask;
10838 const msurface_t *surface;
10839 dp_model_t *model = ent->model;
10842 switch(vid.renderpath)
10844 case RENDERPATH_GL11:
10845 case RENDERPATH_GL13:
10846 case RENDERPATH_GL20:
10848 case RENDERPATH_D3D9:
10849 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10851 case RENDERPATH_D3D10:
10852 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10854 case RENDERPATH_D3D11:
10855 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10857 case RENDERPATH_SOFT:
10858 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10860 case RENDERPATH_GLES2:
10861 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10865 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10867 // R_Mesh_ResetTextureState();
10868 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10869 GL_DepthRange(0, 1);
10870 GL_DepthTest(!r_showdisabledepthtest.integer);
10871 GL_DepthMask(false);
10872 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10874 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10878 qboolean cullbox = ent == r_refdef.scene.worldentity;
10879 const q3mbrush_t *brush;
10880 const bih_t *bih = &model->collision_bih;
10881 const bih_leaf_t *bihleaf;
10882 float vertex3f[3][3];
10883 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10885 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10887 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10889 switch (bihleaf->type)
10892 brush = model->brush.data_brushes + bihleaf->itemindex;
10893 if (brush->colbrushf && brush->colbrushf->numtriangles)
10895 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);
10896 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10897 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10900 case BIH_COLLISIONTRIANGLE:
10901 triangleindex = bihleaf->itemindex;
10902 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10903 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10904 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10905 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);
10906 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10907 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10909 case BIH_RENDERTRIANGLE:
10910 triangleindex = bihleaf->itemindex;
10911 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10912 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10913 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10914 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);
10915 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10916 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10922 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10924 if (r_showtris.integer || (r_shownormals.value != 0))
10926 if (r_showdisabledepthtest.integer)
10928 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10929 GL_DepthMask(false);
10933 GL_BlendFunc(GL_ONE, GL_ZERO);
10934 GL_DepthMask(true);
10936 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10938 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10940 rsurface.texture = R_GetCurrentTexture(surface->texture);
10941 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10943 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10944 if (r_showtris.value > 0)
10946 if (!rsurface.texture->currentlayers->depthmask)
10947 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10948 else if (ent == r_refdef.scene.worldentity)
10949 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10951 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10952 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10953 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10955 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10958 if (r_shownormals.value < 0)
10960 qglBegin(GL_LINES);
10961 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10963 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10964 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10965 qglVertex3f(v[0], v[1], v[2]);
10966 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10967 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10968 qglVertex3f(v[0], v[1], v[2]);
10973 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10975 qglBegin(GL_LINES);
10976 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10978 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10979 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10980 qglVertex3f(v[0], v[1], v[2]);
10981 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10982 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10983 qglVertex3f(v[0], v[1], v[2]);
10987 qglBegin(GL_LINES);
10988 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10990 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10991 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10992 qglVertex3f(v[0], v[1], v[2]);
10993 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10994 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10995 qglVertex3f(v[0], v[1], v[2]);
10999 qglBegin(GL_LINES);
11000 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11002 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11003 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11004 qglVertex3f(v[0], v[1], v[2]);
11005 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11006 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11007 qglVertex3f(v[0], v[1], v[2]);
11014 rsurface.texture = NULL;
11018 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11019 int r_maxsurfacelist = 0;
11020 const msurface_t **r_surfacelist = NULL;
11021 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11023 int i, j, endj, flagsmask;
11024 dp_model_t *model = r_refdef.scene.worldmodel;
11025 msurface_t *surfaces;
11026 unsigned char *update;
11027 int numsurfacelist = 0;
11031 if (r_maxsurfacelist < model->num_surfaces)
11033 r_maxsurfacelist = model->num_surfaces;
11035 Mem_Free((msurface_t**)r_surfacelist);
11036 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11039 RSurf_ActiveWorldEntity();
11041 surfaces = model->data_surfaces;
11042 update = model->brushq1.lightmapupdateflags;
11044 // update light styles on this submodel
11045 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11047 model_brush_lightstyleinfo_t *style;
11048 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11050 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11052 int *list = style->surfacelist;
11053 style->value = r_refdef.scene.lightstylevalue[style->style];
11054 for (j = 0;j < style->numsurfaces;j++)
11055 update[list[j]] = true;
11060 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11064 R_DrawDebugModel();
11065 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11069 rsurface.lightmaptexture = NULL;
11070 rsurface.deluxemaptexture = NULL;
11071 rsurface.uselightmaptexture = false;
11072 rsurface.texture = NULL;
11073 rsurface.rtlight = NULL;
11074 numsurfacelist = 0;
11075 // add visible surfaces to draw list
11076 for (i = 0;i < model->nummodelsurfaces;i++)
11078 j = model->sortedmodelsurfaces[i];
11079 if (r_refdef.viewcache.world_surfacevisible[j])
11080 r_surfacelist[numsurfacelist++] = surfaces + j;
11082 // update lightmaps if needed
11083 if (model->brushq1.firstrender)
11085 model->brushq1.firstrender = false;
11086 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11088 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11092 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11093 if (r_refdef.viewcache.world_surfacevisible[j])
11095 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11097 // don't do anything if there were no surfaces
11098 if (!numsurfacelist)
11100 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11103 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11105 // add to stats if desired
11106 if (r_speeds.integer && !skysurfaces && !depthonly)
11108 r_refdef.stats.world_surfaces += numsurfacelist;
11109 for (j = 0;j < numsurfacelist;j++)
11110 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11113 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11116 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11118 int i, j, endj, flagsmask;
11119 dp_model_t *model = ent->model;
11120 msurface_t *surfaces;
11121 unsigned char *update;
11122 int numsurfacelist = 0;
11126 if (r_maxsurfacelist < model->num_surfaces)
11128 r_maxsurfacelist = model->num_surfaces;
11130 Mem_Free((msurface_t **)r_surfacelist);
11131 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11134 // if the model is static it doesn't matter what value we give for
11135 // wantnormals and wanttangents, so this logic uses only rules applicable
11136 // to a model, knowing that they are meaningless otherwise
11137 if (ent == r_refdef.scene.worldentity)
11138 RSurf_ActiveWorldEntity();
11139 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11140 RSurf_ActiveModelEntity(ent, false, false, false);
11142 RSurf_ActiveModelEntity(ent, true, true, true);
11143 else if (depthonly)
11145 switch (vid.renderpath)
11147 case RENDERPATH_GL20:
11148 case RENDERPATH_D3D9:
11149 case RENDERPATH_D3D10:
11150 case RENDERPATH_D3D11:
11151 case RENDERPATH_SOFT:
11152 case RENDERPATH_GLES2:
11153 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11155 case RENDERPATH_GL13:
11156 case RENDERPATH_GL11:
11157 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11163 switch (vid.renderpath)
11165 case RENDERPATH_GL20:
11166 case RENDERPATH_D3D9:
11167 case RENDERPATH_D3D10:
11168 case RENDERPATH_D3D11:
11169 case RENDERPATH_SOFT:
11170 case RENDERPATH_GLES2:
11171 RSurf_ActiveModelEntity(ent, true, true, false);
11173 case RENDERPATH_GL13:
11174 case RENDERPATH_GL11:
11175 RSurf_ActiveModelEntity(ent, true, false, false);
11180 surfaces = model->data_surfaces;
11181 update = model->brushq1.lightmapupdateflags;
11183 // update light styles
11184 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11186 model_brush_lightstyleinfo_t *style;
11187 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11189 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11191 int *list = style->surfacelist;
11192 style->value = r_refdef.scene.lightstylevalue[style->style];
11193 for (j = 0;j < style->numsurfaces;j++)
11194 update[list[j]] = true;
11199 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11203 R_DrawDebugModel();
11204 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11208 rsurface.lightmaptexture = NULL;
11209 rsurface.deluxemaptexture = NULL;
11210 rsurface.uselightmaptexture = false;
11211 rsurface.texture = NULL;
11212 rsurface.rtlight = NULL;
11213 numsurfacelist = 0;
11214 // add visible surfaces to draw list
11215 for (i = 0;i < model->nummodelsurfaces;i++)
11216 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11217 // don't do anything if there were no surfaces
11218 if (!numsurfacelist)
11220 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11223 // update lightmaps if needed
11227 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11232 R_BuildLightMap(ent, surfaces + j);
11237 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11239 R_BuildLightMap(ent, surfaces + j);
11240 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11242 // add to stats if desired
11243 if (r_speeds.integer && !skysurfaces && !depthonly)
11245 r_refdef.stats.entities_surfaces += numsurfacelist;
11246 for (j = 0;j < numsurfacelist;j++)
11247 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11250 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11253 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11255 static texture_t texture;
11256 static msurface_t surface;
11257 const msurface_t *surfacelist = &surface;
11259 // fake enough texture and surface state to render this geometry
11261 texture.update_lastrenderframe = -1; // regenerate this texture
11262 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11263 texture.currentskinframe = skinframe;
11264 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11265 texture.offsetmapping = OFFSETMAPPING_OFF;
11266 texture.offsetscale = 1;
11267 texture.specularscalemod = 1;
11268 texture.specularpowermod = 1;
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);
11284 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)
11286 static msurface_t surface;
11287 const msurface_t *surfacelist = &surface;
11289 // fake enough texture and surface state to render this geometry
11290 surface.texture = texture;
11291 surface.num_triangles = numtriangles;
11292 surface.num_firsttriangle = firsttriangle;
11293 surface.num_vertices = numvertices;
11294 surface.num_firstvertex = firstvertex;
11297 rsurface.texture = R_GetCurrentTexture(surface.texture);
11298 rsurface.lightmaptexture = NULL;
11299 rsurface.deluxemaptexture = NULL;
11300 rsurface.uselightmaptexture = false;
11301 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);