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_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
212 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)"};
214 extern cvar_t v_glslgamma;
216 extern qboolean v_flipped_state;
218 static struct r_bloomstate_s
223 int bloomwidth, bloomheight;
225 int screentexturewidth, screentextureheight;
226 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
228 int bloomtexturewidth, bloomtextureheight;
229 rtexture_t *texture_bloom;
231 // arrays for rendering the screen passes
232 float screentexcoord2f[8];
233 float bloomtexcoord2f[8];
234 float offsettexcoord2f[8];
236 r_viewport_t viewport;
240 r_waterstate_t r_waterstate;
242 /// shadow volume bsp struct with automatically growing nodes buffer
245 rtexture_t *r_texture_blanknormalmap;
246 rtexture_t *r_texture_white;
247 rtexture_t *r_texture_grey128;
248 rtexture_t *r_texture_black;
249 rtexture_t *r_texture_notexture;
250 rtexture_t *r_texture_whitecube;
251 rtexture_t *r_texture_normalizationcube;
252 rtexture_t *r_texture_fogattenuation;
253 rtexture_t *r_texture_fogheighttexture;
254 rtexture_t *r_texture_gammaramps;
255 unsigned int r_texture_gammaramps_serial;
256 //rtexture_t *r_texture_fogintensity;
257 rtexture_t *r_texture_reflectcube;
259 // TODO: hash lookups?
260 typedef struct cubemapinfo_s
267 int r_texture_numcubemaps;
268 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
270 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
271 unsigned int r_numqueries;
272 unsigned int r_maxqueries;
274 typedef struct r_qwskincache_s
276 char name[MAX_QPATH];
277 skinframe_t *skinframe;
281 static r_qwskincache_t *r_qwskincache;
282 static int r_qwskincache_size;
284 /// vertex coordinates for a quad that covers the screen exactly
285 extern const float r_screenvertex3f[12];
286 extern const float r_d3dscreenvertex3f[12];
287 const float r_screenvertex3f[12] =
294 const float r_d3dscreenvertex3f[12] =
302 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
305 for (i = 0;i < verts;i++)
316 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
319 for (i = 0;i < verts;i++)
329 // FIXME: move this to client?
332 if (gamemode == GAME_NEHAHRA)
334 Cvar_Set("gl_fogenable", "0");
335 Cvar_Set("gl_fogdensity", "0.2");
336 Cvar_Set("gl_fogred", "0.3");
337 Cvar_Set("gl_foggreen", "0.3");
338 Cvar_Set("gl_fogblue", "0.3");
340 r_refdef.fog_density = 0;
341 r_refdef.fog_red = 0;
342 r_refdef.fog_green = 0;
343 r_refdef.fog_blue = 0;
344 r_refdef.fog_alpha = 1;
345 r_refdef.fog_start = 0;
346 r_refdef.fog_end = 16384;
347 r_refdef.fog_height = 1<<30;
348 r_refdef.fog_fadedepth = 128;
349 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
352 static void R_BuildBlankTextures(void)
354 unsigned char data[4];
355 data[2] = 128; // normal X
356 data[1] = 128; // normal Y
357 data[0] = 255; // normal Z
358 data[3] = 128; // height
359 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
377 static void R_BuildNoTexture(void)
380 unsigned char pix[16][16][4];
381 // this makes a light grey/dark grey checkerboard texture
382 for (y = 0;y < 16;y++)
384 for (x = 0;x < 16;x++)
386 if ((y < 8) ^ (x < 8))
402 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
405 static void R_BuildWhiteCube(void)
407 unsigned char data[6*1*1*4];
408 memset(data, 255, sizeof(data));
409 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
412 static void R_BuildNormalizationCube(void)
416 vec_t s, t, intensity;
419 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
420 for (side = 0;side < 6;side++)
422 for (y = 0;y < NORMSIZE;y++)
424 for (x = 0;x < NORMSIZE;x++)
426 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
462 intensity = 127.0f / sqrt(DotProduct(v, v));
463 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
464 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
465 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
466 data[((side*64+y)*64+x)*4+3] = 255;
470 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
474 static void R_BuildFogTexture(void)
478 unsigned char data1[FOGWIDTH][4];
479 //unsigned char data2[FOGWIDTH][4];
482 r_refdef.fogmasktable_start = r_refdef.fog_start;
483 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
484 r_refdef.fogmasktable_range = r_refdef.fogrange;
485 r_refdef.fogmasktable_density = r_refdef.fog_density;
487 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
488 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
490 d = (x * r - r_refdef.fogmasktable_start);
491 if(developer_extra.integer)
492 Con_DPrintf("%f ", d);
494 if (r_fog_exp2.integer)
495 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
497 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
498 if(developer_extra.integer)
499 Con_DPrintf(" : %f ", alpha);
500 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
501 if(developer_extra.integer)
502 Con_DPrintf(" = %f\n", alpha);
503 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
506 for (x = 0;x < FOGWIDTH;x++)
508 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
513 //data2[x][0] = 255 - b;
514 //data2[x][1] = 255 - b;
515 //data2[x][2] = 255 - b;
518 if (r_texture_fogattenuation)
520 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
525 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
526 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
530 static void R_BuildFogHeightTexture(void)
532 unsigned char *inpixels;
540 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
541 if (r_refdef.fogheighttexturename[0])
542 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
545 r_refdef.fog_height_tablesize = 0;
546 if (r_texture_fogheighttexture)
547 R_FreeTexture(r_texture_fogheighttexture);
548 r_texture_fogheighttexture = NULL;
549 if (r_refdef.fog_height_table2d)
550 Mem_Free(r_refdef.fog_height_table2d);
551 r_refdef.fog_height_table2d = NULL;
552 if (r_refdef.fog_height_table1d)
553 Mem_Free(r_refdef.fog_height_table1d);
554 r_refdef.fog_height_table1d = NULL;
558 r_refdef.fog_height_tablesize = size;
559 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
560 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
561 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
563 // LordHavoc: now the magic - what is that table2d for? it is a cooked
564 // average fog color table accounting for every fog layer between a point
565 // and the camera. (Note: attenuation is handled separately!)
566 for (y = 0;y < size;y++)
568 for (x = 0;x < size;x++)
574 for (j = x;j <= y;j++)
576 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582 for (j = x;j >= y;j--)
584 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
589 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
590 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
591 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
592 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
595 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
598 //=======================================================================================================================================================
600 static const char *builtinshaderstring =
601 #include "shader_glsl.h"
604 const char *builtinhlslshaderstring =
605 #include "shader_hlsl.h"
608 char *glslshaderstring = NULL;
609 char *hlslshaderstring = NULL;
611 //=======================================================================================================================================================
613 typedef struct shaderpermutationinfo_s
618 shaderpermutationinfo_t;
620 typedef struct shadermodeinfo_s
622 const char *vertexfilename;
623 const char *geometryfilename;
624 const char *fragmentfilename;
630 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
631 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
633 {"#define USEDIFFUSE\n", " diffuse"},
634 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
635 {"#define USEVIEWTINT\n", " viewtint"},
636 {"#define USECOLORMAPPING\n", " colormapping"},
637 {"#define USESATURATION\n", " saturation"},
638 {"#define USEFOGINSIDE\n", " foginside"},
639 {"#define USEFOGOUTSIDE\n", " fogoutside"},
640 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
641 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
642 {"#define USEGAMMARAMPS\n", " gammaramps"},
643 {"#define USECUBEFILTER\n", " cubefilter"},
644 {"#define USEGLOW\n", " glow"},
645 {"#define USEBLOOM\n", " bloom"},
646 {"#define USESPECULAR\n", " specular"},
647 {"#define USEPOSTPROCESSING\n", " postprocessing"},
648 {"#define USEREFLECTION\n", " reflection"},
649 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
650 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
651 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
652 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
653 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
654 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
655 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
656 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
657 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
658 {"#define USEALPHAKILL\n", " alphakill"},
659 {"#define USEREFLECTCUBE\n", " reflectcube"},
660 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
661 {"#define USEBOUNCEGRID\n", " bouncegrid"},
662 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
665 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
666 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
670 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
686 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 struct r_glsl_permutation_s;
707 typedef struct r_glsl_permutation_s
710 struct r_glsl_permutation_s *hashnext;
712 unsigned int permutation;
714 /// indicates if we have tried compiling this permutation already
716 /// 0 if compilation failed
718 // texture units assigned to each detected uniform
719 int tex_Texture_First;
720 int tex_Texture_Second;
721 int tex_Texture_GammaRamps;
722 int tex_Texture_Normal;
723 int tex_Texture_Color;
724 int tex_Texture_Gloss;
725 int tex_Texture_Glow;
726 int tex_Texture_SecondaryNormal;
727 int tex_Texture_SecondaryColor;
728 int tex_Texture_SecondaryGloss;
729 int tex_Texture_SecondaryGlow;
730 int tex_Texture_Pants;
731 int tex_Texture_Shirt;
732 int tex_Texture_FogHeightTexture;
733 int tex_Texture_FogMask;
734 int tex_Texture_Lightmap;
735 int tex_Texture_Deluxemap;
736 int tex_Texture_Attenuation;
737 int tex_Texture_Cube;
738 int tex_Texture_Refraction;
739 int tex_Texture_Reflection;
740 int tex_Texture_ShadowMap2D;
741 int tex_Texture_CubeProjection;
742 int tex_Texture_ScreenDepth;
743 int tex_Texture_ScreenNormalMap;
744 int tex_Texture_ScreenDiffuse;
745 int tex_Texture_ScreenSpecular;
746 int tex_Texture_ReflectMask;
747 int tex_Texture_ReflectCube;
748 int tex_Texture_BounceGrid;
749 /// locations of detected uniforms in program object, or -1 if not found
750 int loc_Texture_First;
751 int loc_Texture_Second;
752 int loc_Texture_GammaRamps;
753 int loc_Texture_Normal;
754 int loc_Texture_Color;
755 int loc_Texture_Gloss;
756 int loc_Texture_Glow;
757 int loc_Texture_SecondaryNormal;
758 int loc_Texture_SecondaryColor;
759 int loc_Texture_SecondaryGloss;
760 int loc_Texture_SecondaryGlow;
761 int loc_Texture_Pants;
762 int loc_Texture_Shirt;
763 int loc_Texture_FogHeightTexture;
764 int loc_Texture_FogMask;
765 int loc_Texture_Lightmap;
766 int loc_Texture_Deluxemap;
767 int loc_Texture_Attenuation;
768 int loc_Texture_Cube;
769 int loc_Texture_Refraction;
770 int loc_Texture_Reflection;
771 int loc_Texture_ShadowMap2D;
772 int loc_Texture_CubeProjection;
773 int loc_Texture_ScreenDepth;
774 int loc_Texture_ScreenNormalMap;
775 int loc_Texture_ScreenDiffuse;
776 int loc_Texture_ScreenSpecular;
777 int loc_Texture_ReflectMask;
778 int loc_Texture_ReflectCube;
779 int loc_Texture_BounceGrid;
781 int loc_BloomBlur_Parameters;
783 int loc_Color_Ambient;
784 int loc_Color_Diffuse;
785 int loc_Color_Specular;
789 int loc_DeferredColor_Ambient;
790 int loc_DeferredColor_Diffuse;
791 int loc_DeferredColor_Specular;
792 int loc_DeferredMod_Diffuse;
793 int loc_DeferredMod_Specular;
794 int loc_DistortScaleRefractReflect;
797 int loc_FogHeightFade;
799 int loc_FogPlaneViewDist;
800 int loc_FogRangeRecip;
803 int loc_LightPosition;
804 int loc_OffsetMapping_ScaleSteps;
806 int loc_ReflectColor;
807 int loc_ReflectFactor;
808 int loc_ReflectOffset;
809 int loc_RefractColor;
811 int loc_ScreenCenterRefractReflect;
812 int loc_ScreenScaleRefractReflect;
813 int loc_ScreenToDepth;
814 int loc_ShadowMap_Parameters;
815 int loc_ShadowMap_TextureScale;
816 int loc_SpecularPower;
821 int loc_ViewTintColor;
823 int loc_ModelToLight;
825 int loc_BackgroundTexMatrix;
826 int loc_ModelViewProjectionMatrix;
827 int loc_ModelViewMatrix;
828 int loc_PixelToScreenTexCoord;
829 int loc_ModelToReflectCube;
830 int loc_ShadowMapMatrix;
831 int loc_BloomColorSubtract;
832 int loc_NormalmapScrollBlend;
833 int loc_BounceGridMatrix;
834 int loc_BounceGridIntensity;
836 r_glsl_permutation_t;
838 #define SHADERPERMUTATION_HASHSIZE 256
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
845 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
851 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
853 #define SHADERSTATICPARMS_COUNT 7
855 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
856 static int shaderstaticparms_count = 0;
858 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
859 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
860 qboolean R_CompileShader_CheckStaticParms(void)
862 static int r_compileshader_staticparms_save[1];
863 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
864 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
867 if (r_glsl_saturation_redcompensate.integer)
868 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
869 if (r_glsl_vertextextureblend_usebothalphas.integer)
870 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
871 if (r_shadow_glossexact.integer)
872 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
873 if (r_glsl_postprocess.integer)
875 if (r_glsl_postprocess_uservec1_enable.integer)
876 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
877 if (r_glsl_postprocess_uservec2_enable.integer)
878 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
879 if (r_glsl_postprocess_uservec3_enable.integer)
880 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
881 if (r_glsl_postprocess_uservec4_enable.integer)
882 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
887 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
888 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
889 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
891 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
892 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
894 shaderstaticparms_count = 0;
897 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
898 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
899 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
900 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
901 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
902 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
903 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
906 /// information about each possible shader permutation
907 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
908 /// currently selected permutation
909 r_glsl_permutation_t *r_glsl_permutation;
910 /// storage for permutations linked in the hash table
911 memexpandablearray_t r_glsl_permutationarray;
913 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
915 //unsigned int hashdepth = 0;
916 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
917 r_glsl_permutation_t *p;
918 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
920 if (p->mode == mode && p->permutation == permutation)
922 //if (hashdepth > 10)
923 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
930 p->permutation = permutation;
931 p->hashnext = r_glsl_permutationhash[mode][hashindex];
932 r_glsl_permutationhash[mode][hashindex] = p;
933 //if (hashdepth > 10)
934 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
938 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
941 if (!filename || !filename[0])
943 if (!strcmp(filename, "glsl/default.glsl"))
945 if (!glslshaderstring)
947 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
948 if (glslshaderstring)
949 Con_DPrintf("Loading shaders from file %s...\n", filename);
951 glslshaderstring = (char *)builtinshaderstring;
953 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
954 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
957 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
960 if (printfromdisknotice)
961 Con_DPrintf("from disk %s... ", filename);
967 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
971 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
972 char *vertexstring, *geometrystring, *fragmentstring;
973 char permutationname[256];
974 int vertstrings_count = 0;
975 int geomstrings_count = 0;
976 int fragstrings_count = 0;
977 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
978 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
979 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
986 permutationname[0] = 0;
987 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
988 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
989 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
991 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
993 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
994 if(vid.support.gl20shaders130)
996 vertstrings_list[vertstrings_count++] = "#version 130\n";
997 geomstrings_list[geomstrings_count++] = "#version 130\n";
998 fragstrings_list[fragstrings_count++] = "#version 130\n";
999 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1000 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1001 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1004 // the first pretext is which type of shader to compile as
1005 // (later these will all be bound together as a program object)
1006 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1007 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1008 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1010 // the second pretext is the mode (for example a light source)
1011 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1012 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1013 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1014 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1016 // now add all the permutation pretexts
1017 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1019 if (permutation & (1<<i))
1021 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1022 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1023 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1024 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1028 // keep line numbers correct
1029 vertstrings_list[vertstrings_count++] = "\n";
1030 geomstrings_list[geomstrings_count++] = "\n";
1031 fragstrings_list[fragstrings_count++] = "\n";
1036 R_CompileShader_AddStaticParms(mode, permutation);
1037 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1038 vertstrings_count += shaderstaticparms_count;
1039 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1040 geomstrings_count += shaderstaticparms_count;
1041 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042 fragstrings_count += shaderstaticparms_count;
1044 // now append the shader text itself
1045 vertstrings_list[vertstrings_count++] = vertexstring;
1046 geomstrings_list[geomstrings_count++] = geometrystring;
1047 fragstrings_list[fragstrings_count++] = fragmentstring;
1049 // if any sources were NULL, clear the respective list
1051 vertstrings_count = 0;
1052 if (!geometrystring)
1053 geomstrings_count = 0;
1054 if (!fragmentstring)
1055 fragstrings_count = 0;
1057 // compile the shader program
1058 if (vertstrings_count + geomstrings_count + fragstrings_count)
1059 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1063 qglUseProgram(p->program);CHECKGLERROR
1064 // look up all the uniform variable names we care about, so we don't
1065 // have to look them up every time we set them
1067 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1068 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1069 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1070 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1071 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1072 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1073 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1074 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1075 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1076 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1077 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1078 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1079 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1080 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1081 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1082 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1083 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1084 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1085 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1086 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1087 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1088 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1089 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1090 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1091 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1092 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1093 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1094 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1095 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1096 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1097 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1098 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1099 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1100 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1101 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1102 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1103 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1104 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1105 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1106 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1107 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1108 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1109 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1110 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1111 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1112 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1113 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1114 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1115 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1116 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1117 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1118 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1119 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1120 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1121 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1122 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1123 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1124 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1125 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1126 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1127 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1128 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1129 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1130 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1131 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1132 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1133 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1134 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1135 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1136 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1137 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1138 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1139 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1140 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1141 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1142 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1143 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1144 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1145 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1146 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1147 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1148 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1149 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1150 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1151 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1152 // initialize the samplers to refer to the texture units we use
1153 p->tex_Texture_First = -1;
1154 p->tex_Texture_Second = -1;
1155 p->tex_Texture_GammaRamps = -1;
1156 p->tex_Texture_Normal = -1;
1157 p->tex_Texture_Color = -1;
1158 p->tex_Texture_Gloss = -1;
1159 p->tex_Texture_Glow = -1;
1160 p->tex_Texture_SecondaryNormal = -1;
1161 p->tex_Texture_SecondaryColor = -1;
1162 p->tex_Texture_SecondaryGloss = -1;
1163 p->tex_Texture_SecondaryGlow = -1;
1164 p->tex_Texture_Pants = -1;
1165 p->tex_Texture_Shirt = -1;
1166 p->tex_Texture_FogHeightTexture = -1;
1167 p->tex_Texture_FogMask = -1;
1168 p->tex_Texture_Lightmap = -1;
1169 p->tex_Texture_Deluxemap = -1;
1170 p->tex_Texture_Attenuation = -1;
1171 p->tex_Texture_Cube = -1;
1172 p->tex_Texture_Refraction = -1;
1173 p->tex_Texture_Reflection = -1;
1174 p->tex_Texture_ShadowMap2D = -1;
1175 p->tex_Texture_CubeProjection = -1;
1176 p->tex_Texture_ScreenDepth = -1;
1177 p->tex_Texture_ScreenNormalMap = -1;
1178 p->tex_Texture_ScreenDiffuse = -1;
1179 p->tex_Texture_ScreenSpecular = -1;
1180 p->tex_Texture_ReflectMask = -1;
1181 p->tex_Texture_ReflectCube = -1;
1182 p->tex_Texture_BounceGrid = -1;
1184 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1185 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1186 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1187 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1188 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1189 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1190 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1191 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1192 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1193 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1194 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1195 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1196 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1197 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1198 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1199 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1200 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1201 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1202 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1203 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1204 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1205 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1206 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1207 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1208 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1209 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1210 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1211 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1212 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1213 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1215 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1218 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1222 Mem_Free(vertexstring);
1224 Mem_Free(geometrystring);
1226 Mem_Free(fragmentstring);
1229 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1231 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1232 if (r_glsl_permutation != perm)
1234 r_glsl_permutation = perm;
1235 if (!r_glsl_permutation->program)
1237 if (!r_glsl_permutation->compiled)
1238 R_GLSL_CompilePermutation(perm, mode, permutation);
1239 if (!r_glsl_permutation->program)
1241 // remove features until we find a valid permutation
1243 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1245 // reduce i more quickly whenever it would not remove any bits
1246 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1247 if (!(permutation & j))
1250 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1251 if (!r_glsl_permutation->compiled)
1252 R_GLSL_CompilePermutation(perm, mode, permutation);
1253 if (r_glsl_permutation->program)
1256 if (i >= SHADERPERMUTATION_COUNT)
1258 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1259 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1260 qglUseProgram(0);CHECKGLERROR
1261 return; // no bit left to clear, entire mode is broken
1266 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1268 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1269 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1270 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1277 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1278 extern D3DCAPS9 vid_d3d9caps;
1281 struct r_hlsl_permutation_s;
1282 typedef struct r_hlsl_permutation_s
1284 /// hash lookup data
1285 struct r_hlsl_permutation_s *hashnext;
1287 unsigned int permutation;
1289 /// indicates if we have tried compiling this permutation already
1291 /// NULL if compilation failed
1292 IDirect3DVertexShader9 *vertexshader;
1293 IDirect3DPixelShader9 *pixelshader;
1295 r_hlsl_permutation_t;
1297 typedef enum D3DVSREGISTER_e
1299 D3DVSREGISTER_TexMatrix = 0, // float4x4
1300 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1301 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1302 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1303 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1304 D3DVSREGISTER_ModelToLight = 20, // float4x4
1305 D3DVSREGISTER_EyePosition = 24,
1306 D3DVSREGISTER_FogPlane = 25,
1307 D3DVSREGISTER_LightDir = 26,
1308 D3DVSREGISTER_LightPosition = 27,
1312 typedef enum D3DPSREGISTER_e
1314 D3DPSREGISTER_Alpha = 0,
1315 D3DPSREGISTER_BloomBlur_Parameters = 1,
1316 D3DPSREGISTER_ClientTime = 2,
1317 D3DPSREGISTER_Color_Ambient = 3,
1318 D3DPSREGISTER_Color_Diffuse = 4,
1319 D3DPSREGISTER_Color_Specular = 5,
1320 D3DPSREGISTER_Color_Glow = 6,
1321 D3DPSREGISTER_Color_Pants = 7,
1322 D3DPSREGISTER_Color_Shirt = 8,
1323 D3DPSREGISTER_DeferredColor_Ambient = 9,
1324 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1325 D3DPSREGISTER_DeferredColor_Specular = 11,
1326 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1327 D3DPSREGISTER_DeferredMod_Specular = 13,
1328 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1329 D3DPSREGISTER_EyePosition = 15, // unused
1330 D3DPSREGISTER_FogColor = 16,
1331 D3DPSREGISTER_FogHeightFade = 17,
1332 D3DPSREGISTER_FogPlane = 18,
1333 D3DPSREGISTER_FogPlaneViewDist = 19,
1334 D3DPSREGISTER_FogRangeRecip = 20,
1335 D3DPSREGISTER_LightColor = 21,
1336 D3DPSREGISTER_LightDir = 22, // unused
1337 D3DPSREGISTER_LightPosition = 23,
1338 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1339 D3DPSREGISTER_PixelSize = 25,
1340 D3DPSREGISTER_ReflectColor = 26,
1341 D3DPSREGISTER_ReflectFactor = 27,
1342 D3DPSREGISTER_ReflectOffset = 28,
1343 D3DPSREGISTER_RefractColor = 29,
1344 D3DPSREGISTER_Saturation = 30,
1345 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1346 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1347 D3DPSREGISTER_ScreenToDepth = 33,
1348 D3DPSREGISTER_ShadowMap_Parameters = 34,
1349 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1350 D3DPSREGISTER_SpecularPower = 36,
1351 D3DPSREGISTER_UserVec1 = 37,
1352 D3DPSREGISTER_UserVec2 = 38,
1353 D3DPSREGISTER_UserVec3 = 39,
1354 D3DPSREGISTER_UserVec4 = 40,
1355 D3DPSREGISTER_ViewTintColor = 41,
1356 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1357 D3DPSREGISTER_BloomColorSubtract = 43,
1358 D3DPSREGISTER_ViewToLight = 44, // float4x4
1359 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1360 D3DPSREGISTER_NormalmapScrollBlend = 52,
1365 /// information about each possible shader permutation
1366 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1367 /// currently selected permutation
1368 r_hlsl_permutation_t *r_hlsl_permutation;
1369 /// storage for permutations linked in the hash table
1370 memexpandablearray_t r_hlsl_permutationarray;
1372 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1374 //unsigned int hashdepth = 0;
1375 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1376 r_hlsl_permutation_t *p;
1377 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1379 if (p->mode == mode && p->permutation == permutation)
1381 //if (hashdepth > 10)
1382 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1387 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1389 p->permutation = permutation;
1390 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1391 r_hlsl_permutationhash[mode][hashindex] = p;
1392 //if (hashdepth > 10)
1393 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1397 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1400 if (!filename || !filename[0])
1402 if (!strcmp(filename, "hlsl/default.hlsl"))
1404 if (!hlslshaderstring)
1406 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1407 if (hlslshaderstring)
1408 Con_DPrintf("Loading shaders from file %s...\n", filename);
1410 hlslshaderstring = (char *)builtinhlslshaderstring;
1412 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1413 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1414 return shaderstring;
1416 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1419 if (printfromdisknotice)
1420 Con_DPrintf("from disk %s... ", filename);
1421 return shaderstring;
1423 return shaderstring;
1427 //#include <d3dx9shader.h>
1428 //#include <d3dx9mesh.h>
1430 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1432 DWORD *vsbin = NULL;
1433 DWORD *psbin = NULL;
1434 fs_offset_t vsbinsize;
1435 fs_offset_t psbinsize;
1436 // IDirect3DVertexShader9 *vs = NULL;
1437 // IDirect3DPixelShader9 *ps = NULL;
1438 ID3DXBuffer *vslog = NULL;
1439 ID3DXBuffer *vsbuffer = NULL;
1440 ID3DXConstantTable *vsconstanttable = NULL;
1441 ID3DXBuffer *pslog = NULL;
1442 ID3DXBuffer *psbuffer = NULL;
1443 ID3DXConstantTable *psconstanttable = NULL;
1446 char temp[MAX_INPUTLINE];
1447 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1448 qboolean debugshader = gl_paranoid.integer != 0;
1449 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1450 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1453 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1454 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1456 if ((!vsbin && vertstring) || (!psbin && fragstring))
1458 const char* dllnames_d3dx9 [] =
1482 dllhandle_t d3dx9_dll = NULL;
1483 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1484 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1485 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1486 dllfunction_t d3dx9_dllfuncs[] =
1488 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1489 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1490 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1493 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1495 DWORD shaderflags = 0;
1497 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1498 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1499 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1500 if (vertstring && vertstring[0])
1504 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1505 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1506 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1507 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1510 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1513 vsbinsize = vsbuffer->GetBufferSize();
1514 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1515 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1516 vsbuffer->Release();
1520 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1521 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1525 if (fragstring && fragstring[0])
1529 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1530 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1531 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1532 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1535 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1538 psbinsize = psbuffer->GetBufferSize();
1539 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1540 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1541 psbuffer->Release();
1545 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1546 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1550 Sys_UnloadLibrary(&d3dx9_dll);
1553 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1557 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1558 if (FAILED(vsresult))
1559 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1560 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1561 if (FAILED(psresult))
1562 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1564 // free the shader data
1565 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1566 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1569 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1572 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1573 int vertstring_length = 0;
1574 int geomstring_length = 0;
1575 int fragstring_length = 0;
1577 char *vertexstring, *geometrystring, *fragmentstring;
1578 char *vertstring, *geomstring, *fragstring;
1579 char permutationname[256];
1580 char cachename[256];
1581 int vertstrings_count = 0;
1582 int geomstrings_count = 0;
1583 int fragstrings_count = 0;
1584 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1585 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1586 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1591 p->vertexshader = NULL;
1592 p->pixelshader = NULL;
1594 permutationname[0] = 0;
1596 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1597 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1598 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1600 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1601 strlcat(cachename, "hlsl/", sizeof(cachename));
1603 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1604 vertstrings_count = 0;
1605 geomstrings_count = 0;
1606 fragstrings_count = 0;
1607 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1608 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1609 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1611 // the first pretext is which type of shader to compile as
1612 // (later these will all be bound together as a program object)
1613 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1614 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1615 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1617 // the second pretext is the mode (for example a light source)
1618 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1619 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1620 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1621 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1622 strlcat(cachename, modeinfo->name, sizeof(cachename));
1624 // now add all the permutation pretexts
1625 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1627 if (permutation & (1<<i))
1629 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1630 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1631 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1632 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1633 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1637 // keep line numbers correct
1638 vertstrings_list[vertstrings_count++] = "\n";
1639 geomstrings_list[geomstrings_count++] = "\n";
1640 fragstrings_list[fragstrings_count++] = "\n";
1645 R_CompileShader_AddStaticParms(mode, permutation);
1646 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1647 vertstrings_count += shaderstaticparms_count;
1648 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1649 geomstrings_count += shaderstaticparms_count;
1650 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1651 fragstrings_count += shaderstaticparms_count;
1653 // replace spaces in the cachename with _ characters
1654 for (i = 0;cachename[i];i++)
1655 if (cachename[i] == ' ')
1658 // now append the shader text itself
1659 vertstrings_list[vertstrings_count++] = vertexstring;
1660 geomstrings_list[geomstrings_count++] = geometrystring;
1661 fragstrings_list[fragstrings_count++] = fragmentstring;
1663 // if any sources were NULL, clear the respective list
1665 vertstrings_count = 0;
1666 if (!geometrystring)
1667 geomstrings_count = 0;
1668 if (!fragmentstring)
1669 fragstrings_count = 0;
1671 vertstring_length = 0;
1672 for (i = 0;i < vertstrings_count;i++)
1673 vertstring_length += strlen(vertstrings_list[i]);
1674 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1675 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1676 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1678 geomstring_length = 0;
1679 for (i = 0;i < geomstrings_count;i++)
1680 geomstring_length += strlen(geomstrings_list[i]);
1681 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1682 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1683 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1685 fragstring_length = 0;
1686 for (i = 0;i < fragstrings_count;i++)
1687 fragstring_length += strlen(fragstrings_list[i]);
1688 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1689 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1690 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1692 // try to load the cached shader, or generate one
1693 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1695 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1696 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1698 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1702 Mem_Free(vertstring);
1704 Mem_Free(geomstring);
1706 Mem_Free(fragstring);
1708 Mem_Free(vertexstring);
1710 Mem_Free(geometrystring);
1712 Mem_Free(fragmentstring);
1715 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1716 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1717 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);}
1718 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);}
1719 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);}
1720 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);}
1722 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1723 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1724 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);}
1725 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);}
1726 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);}
1727 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);}
1729 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1731 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1732 if (r_hlsl_permutation != perm)
1734 r_hlsl_permutation = perm;
1735 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1737 if (!r_hlsl_permutation->compiled)
1738 R_HLSL_CompilePermutation(perm, mode, permutation);
1739 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1741 // remove features until we find a valid permutation
1743 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1745 // reduce i more quickly whenever it would not remove any bits
1746 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1747 if (!(permutation & j))
1750 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1751 if (!r_hlsl_permutation->compiled)
1752 R_HLSL_CompilePermutation(perm, mode, permutation);
1753 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1756 if (i >= SHADERPERMUTATION_COUNT)
1758 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1759 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1760 return; // no bit left to clear, entire mode is broken
1764 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1765 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1767 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1768 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1769 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1773 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1775 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1776 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1777 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1778 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1781 void R_GLSL_Restart_f(void)
1783 unsigned int i, limit;
1784 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1785 Mem_Free(glslshaderstring);
1786 glslshaderstring = NULL;
1787 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1788 Mem_Free(hlslshaderstring);
1789 hlslshaderstring = NULL;
1790 switch(vid.renderpath)
1792 case RENDERPATH_D3D9:
1795 r_hlsl_permutation_t *p;
1796 r_hlsl_permutation = NULL;
1797 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1798 for (i = 0;i < limit;i++)
1800 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1802 if (p->vertexshader)
1803 IDirect3DVertexShader9_Release(p->vertexshader);
1805 IDirect3DPixelShader9_Release(p->pixelshader);
1806 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1809 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1813 case RENDERPATH_D3D10:
1814 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1816 case RENDERPATH_D3D11:
1817 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1819 case RENDERPATH_GL20:
1820 case RENDERPATH_GLES2:
1822 r_glsl_permutation_t *p;
1823 r_glsl_permutation = NULL;
1824 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1825 for (i = 0;i < limit;i++)
1827 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1829 GL_Backend_FreeProgram(p->program);
1830 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1833 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1836 case RENDERPATH_GL13:
1837 case RENDERPATH_GL11:
1839 case RENDERPATH_SOFT:
1844 void R_GLSL_DumpShader_f(void)
1849 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1852 FS_Print(file, "/* The engine may define the following macros:\n");
1853 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1854 for (i = 0;i < SHADERMODE_COUNT;i++)
1855 FS_Print(file, glslshadermodeinfo[i].pretext);
1856 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1857 FS_Print(file, shaderpermutationinfo[i].pretext);
1858 FS_Print(file, "*/\n");
1859 FS_Print(file, builtinshaderstring);
1861 Con_Printf("glsl/default.glsl written\n");
1864 Con_Printf("failed to write to glsl/default.glsl\n");
1866 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1869 FS_Print(file, "/* The engine may define the following macros:\n");
1870 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871 for (i = 0;i < SHADERMODE_COUNT;i++)
1872 FS_Print(file, hlslshadermodeinfo[i].pretext);
1873 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874 FS_Print(file, shaderpermutationinfo[i].pretext);
1875 FS_Print(file, "*/\n");
1876 FS_Print(file, builtinhlslshaderstring);
1878 Con_Printf("hlsl/default.hlsl written\n");
1881 Con_Printf("failed to write to hlsl/default.hlsl\n");
1884 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1887 texturemode = GL_MODULATE;
1888 switch (vid.renderpath)
1890 case RENDERPATH_D3D9:
1892 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))));
1893 R_Mesh_TexBind(GL20TU_FIRST , first );
1894 R_Mesh_TexBind(GL20TU_SECOND, second);
1897 case RENDERPATH_D3D10:
1898 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1900 case RENDERPATH_D3D11:
1901 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1903 case RENDERPATH_GL20:
1904 case RENDERPATH_GLES2:
1905 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))));
1906 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1907 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1909 case RENDERPATH_GL13:
1910 R_Mesh_TexBind(0, first );
1911 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1912 R_Mesh_TexBind(1, second);
1914 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1916 case RENDERPATH_GL11:
1917 R_Mesh_TexBind(0, first );
1919 case RENDERPATH_SOFT:
1920 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))));
1921 R_Mesh_TexBind(GL20TU_FIRST , first );
1922 R_Mesh_TexBind(GL20TU_SECOND, second);
1927 void R_SetupShader_DepthOrShadow(void)
1929 switch (vid.renderpath)
1931 case RENDERPATH_D3D9:
1933 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1936 case RENDERPATH_D3D10:
1937 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1939 case RENDERPATH_D3D11:
1940 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1942 case RENDERPATH_GL20:
1943 case RENDERPATH_GLES2:
1944 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1946 case RENDERPATH_GL13:
1947 R_Mesh_TexBind(0, 0);
1948 R_Mesh_TexBind(1, 0);
1950 case RENDERPATH_GL11:
1951 R_Mesh_TexBind(0, 0);
1953 case RENDERPATH_SOFT:
1954 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1959 void R_SetupShader_ShowDepth(void)
1961 switch (vid.renderpath)
1963 case RENDERPATH_D3D9:
1965 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1968 case RENDERPATH_D3D10:
1969 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1971 case RENDERPATH_D3D11:
1972 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1974 case RENDERPATH_GL20:
1975 case RENDERPATH_GLES2:
1976 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1978 case RENDERPATH_GL13:
1980 case RENDERPATH_GL11:
1982 case RENDERPATH_SOFT:
1983 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1988 extern qboolean r_shadow_usingdeferredprepass;
1989 extern cvar_t r_shadow_deferred_8bitrange;
1990 extern rtexture_t *r_shadow_attenuationgradienttexture;
1991 extern rtexture_t *r_shadow_attenuation2dtexture;
1992 extern rtexture_t *r_shadow_attenuation3dtexture;
1993 extern qboolean r_shadow_usingshadowmap2d;
1994 extern qboolean r_shadow_usingshadowmaportho;
1995 extern float r_shadow_shadowmap_texturescale[2];
1996 extern float r_shadow_shadowmap_parameters[4];
1997 extern qboolean r_shadow_shadowmapvsdct;
1998 extern qboolean r_shadow_shadowmapsampler;
1999 extern int r_shadow_shadowmappcf;
2000 extern rtexture_t *r_shadow_shadowmap2dtexture;
2001 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2002 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2003 extern matrix4x4_t r_shadow_shadowmapmatrix;
2004 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2005 extern int r_shadow_prepass_width;
2006 extern int r_shadow_prepass_height;
2007 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2008 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2009 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2010 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2011 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2013 #define BLENDFUNC_ALLOWS_COLORMOD 1
2014 #define BLENDFUNC_ALLOWS_FOG 2
2015 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2016 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2017 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2018 static int R_BlendFuncFlags(int src, int dst)
2022 // a blendfunc allows colormod if:
2023 // a) it can never keep the destination pixel invariant, or
2024 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2025 // this is to prevent unintended side effects from colormod
2027 // a blendfunc allows fog if:
2028 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2029 // this is to prevent unintended side effects from fog
2031 // these checks are the output of fogeval.pl
2033 r |= BLENDFUNC_ALLOWS_COLORMOD;
2034 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2036 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2037 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2038 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2041 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2043 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2044 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2045 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2046 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2047 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2048 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2049 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2052 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2053 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2054 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059 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)
2061 // select a permutation of the lighting shader appropriate to this
2062 // combination of texture, entity, light source, and fogging, only use the
2063 // minimum features necessary to avoid wasting rendering time in the
2064 // fragment shader on features that are not being used
2065 unsigned int permutation = 0;
2066 unsigned int mode = 0;
2068 static float dummy_colormod[3] = {1, 1, 1};
2069 float *colormod = rsurface.colormod;
2071 matrix4x4_t tempmatrix;
2072 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2073 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2074 permutation |= SHADERPERMUTATION_ALPHAKILL;
2075 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2076 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2077 if (rsurfacepass == RSURFPASS_BACKGROUND)
2079 // distorted background
2080 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2082 mode = SHADERMODE_WATER;
2083 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2085 // this is the right thing to do for wateralpha
2086 GL_BlendFunc(GL_ONE, GL_ZERO);
2087 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2091 // this is the right thing to do for entity alpha
2092 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2093 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2096 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2098 mode = SHADERMODE_REFRACTION;
2099 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2100 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2104 mode = SHADERMODE_GENERIC;
2105 permutation |= SHADERPERMUTATION_DIFFUSE;
2106 GL_BlendFunc(GL_ONE, GL_ZERO);
2107 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2110 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2112 if (r_glsl_offsetmapping.integer)
2114 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2115 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2116 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2117 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2118 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2120 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2121 if (r_glsl_offsetmapping_reliefmapping.integer)
2122 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2125 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2126 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2127 // normalmap (deferred prepass), may use alpha test on diffuse
2128 mode = SHADERMODE_DEFERREDGEOMETRY;
2129 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2130 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2131 GL_BlendFunc(GL_ONE, GL_ZERO);
2132 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2134 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2136 if (r_glsl_offsetmapping.integer)
2138 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2139 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2140 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2141 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2142 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2144 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2145 if (r_glsl_offsetmapping_reliefmapping.integer)
2146 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2149 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2150 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2152 mode = SHADERMODE_LIGHTSOURCE;
2153 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2154 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2155 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2156 permutation |= SHADERPERMUTATION_CUBEFILTER;
2157 if (diffusescale > 0)
2158 permutation |= SHADERPERMUTATION_DIFFUSE;
2159 if (specularscale > 0)
2160 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2161 if (r_refdef.fogenabled)
2162 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2163 if (rsurface.texture->colormapping)
2164 permutation |= SHADERPERMUTATION_COLORMAPPING;
2165 if (r_shadow_usingshadowmap2d)
2167 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2168 if(r_shadow_shadowmapvsdct)
2169 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2171 if (r_shadow_shadowmapsampler)
2172 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2173 if (r_shadow_shadowmappcf > 1)
2174 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2175 else if (r_shadow_shadowmappcf)
2176 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2178 if (rsurface.texture->reflectmasktexture)
2179 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2180 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2181 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2183 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2185 if (r_glsl_offsetmapping.integer)
2187 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2188 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2189 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2190 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2191 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2193 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2194 if (r_glsl_offsetmapping_reliefmapping.integer)
2195 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2198 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200 // unshaded geometry (fullbright or ambient model lighting)
2201 mode = SHADERMODE_FLATCOLOR;
2202 ambientscale = diffusescale = specularscale = 0;
2203 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2204 permutation |= SHADERPERMUTATION_GLOW;
2205 if (r_refdef.fogenabled)
2206 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2207 if (rsurface.texture->colormapping)
2208 permutation |= SHADERPERMUTATION_COLORMAPPING;
2209 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2211 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2212 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2214 if (r_shadow_shadowmapsampler)
2215 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2216 if (r_shadow_shadowmappcf > 1)
2217 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2218 else if (r_shadow_shadowmappcf)
2219 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2221 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2222 permutation |= SHADERPERMUTATION_REFLECTION;
2223 if (rsurface.texture->reflectmasktexture)
2224 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2225 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2226 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2228 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2230 if (r_glsl_offsetmapping.integer)
2232 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2233 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2234 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2235 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2236 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2238 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2239 if (r_glsl_offsetmapping_reliefmapping.integer)
2240 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2243 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245 // directional model lighting
2246 mode = SHADERMODE_LIGHTDIRECTION;
2247 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2248 permutation |= SHADERPERMUTATION_GLOW;
2249 permutation |= SHADERPERMUTATION_DIFFUSE;
2250 if (specularscale > 0)
2251 permutation |= SHADERPERMUTATION_SPECULAR;
2252 if (r_refdef.fogenabled)
2253 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254 if (rsurface.texture->colormapping)
2255 permutation |= SHADERPERMUTATION_COLORMAPPING;
2256 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2258 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2261 if (r_shadow_shadowmapsampler)
2262 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2263 if (r_shadow_shadowmappcf > 1)
2264 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2265 else if (r_shadow_shadowmappcf)
2266 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2268 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2269 permutation |= SHADERPERMUTATION_REFLECTION;
2270 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2271 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2272 if (rsurface.texture->reflectmasktexture)
2273 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2274 if (r_shadow_bouncegridtexture)
2276 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2277 if (r_shadow_bouncegriddirectional)
2278 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2280 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2283 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2285 if (r_glsl_offsetmapping.integer)
2287 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2288 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2289 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2290 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2291 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2293 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2294 if (r_glsl_offsetmapping_reliefmapping.integer)
2295 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2298 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2299 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2300 // ambient model lighting
2301 mode = SHADERMODE_LIGHTDIRECTION;
2302 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2303 permutation |= SHADERPERMUTATION_GLOW;
2304 if (r_refdef.fogenabled)
2305 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2306 if (rsurface.texture->colormapping)
2307 permutation |= SHADERPERMUTATION_COLORMAPPING;
2308 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2311 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313 if (r_shadow_shadowmapsampler)
2314 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2315 if (r_shadow_shadowmappcf > 1)
2316 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2317 else if (r_shadow_shadowmappcf)
2318 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2320 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2321 permutation |= SHADERPERMUTATION_REFLECTION;
2322 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2323 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2324 if (rsurface.texture->reflectmasktexture)
2325 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2326 if (r_shadow_bouncegridtexture)
2328 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2329 if (r_shadow_bouncegriddirectional)
2330 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2332 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2337 if (r_glsl_offsetmapping.integer)
2339 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2340 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2341 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2342 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2343 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2345 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2346 if (r_glsl_offsetmapping_reliefmapping.integer)
2347 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2350 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2351 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2353 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2354 permutation |= SHADERPERMUTATION_GLOW;
2355 if (r_refdef.fogenabled)
2356 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2357 if (rsurface.texture->colormapping)
2358 permutation |= SHADERPERMUTATION_COLORMAPPING;
2359 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2361 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2362 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2364 if (r_shadow_shadowmapsampler)
2365 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2366 if (r_shadow_shadowmappcf > 1)
2367 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2368 else if (r_shadow_shadowmappcf)
2369 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2371 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2372 permutation |= SHADERPERMUTATION_REFLECTION;
2373 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2374 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2375 if (rsurface.texture->reflectmasktexture)
2376 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2377 if (FAKELIGHT_ENABLED)
2379 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2380 mode = SHADERMODE_FAKELIGHT;
2381 permutation |= SHADERPERMUTATION_DIFFUSE;
2382 if (specularscale > 0)
2383 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2385 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2387 // deluxemapping (light direction texture)
2388 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2389 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2391 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392 permutation |= SHADERPERMUTATION_DIFFUSE;
2393 if (specularscale > 0)
2394 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2396 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2398 // fake deluxemapping (uniform light direction in tangentspace)
2399 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2400 permutation |= SHADERPERMUTATION_DIFFUSE;
2401 if (specularscale > 0)
2402 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2404 else if (rsurface.uselightmaptexture)
2406 // ordinary lightmapping (q1bsp, q3bsp)
2407 mode = SHADERMODE_LIGHTMAP;
2411 // ordinary vertex coloring (q3bsp)
2412 mode = SHADERMODE_VERTEXCOLOR;
2414 if (r_shadow_bouncegridtexture)
2416 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417 if (r_shadow_bouncegriddirectional)
2418 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2420 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2423 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2424 colormod = dummy_colormod;
2425 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2426 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2427 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2428 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2429 switch(vid.renderpath)
2431 case RENDERPATH_D3D9:
2433 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);
2434 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2435 R_SetupShader_SetPermutationHLSL(mode, permutation);
2436 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2437 if (mode == SHADERMODE_LIGHTSOURCE)
2439 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2440 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2444 if (mode == SHADERMODE_LIGHTDIRECTION)
2446 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2449 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2450 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2451 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2452 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2453 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2455 if (mode == SHADERMODE_LIGHTSOURCE)
2457 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2458 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2459 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2460 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2461 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2463 // additive passes are only darkened by fog, not tinted
2464 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2465 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2469 if (mode == SHADERMODE_FLATCOLOR)
2471 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2473 else if (mode == SHADERMODE_LIGHTDIRECTION)
2475 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]);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2478 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2479 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2480 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2481 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2487 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);
2488 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);
2489 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2491 // additive passes are only darkened by fog, not tinted
2492 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2493 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2495 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2496 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);
2497 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2499 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2501 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2502 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2503 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2504 if (mode == SHADERMODE_WATER)
2505 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2507 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2508 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2510 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));
2511 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2512 if (rsurface.texture->pantstexture)
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2515 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2516 if (rsurface.texture->shirttexture)
2517 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2520 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2521 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2522 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2523 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2524 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));
2525 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2526 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2528 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2529 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2530 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2531 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2532 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2533 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2534 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2535 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2536 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2537 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2538 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2539 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2540 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2541 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2542 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2543 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2544 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2545 if (rsurfacepass == RSURFPASS_BACKGROUND)
2547 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2548 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2549 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2553 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2555 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2556 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2557 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2558 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2559 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2561 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2562 if (rsurface.rtlight)
2564 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2565 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2570 case RENDERPATH_D3D10:
2571 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2573 case RENDERPATH_D3D11:
2574 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2576 case RENDERPATH_GL20:
2577 case RENDERPATH_GLES2:
2578 if (!vid.useinterleavedarrays)
2580 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);
2581 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2582 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2583 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2584 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2585 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2586 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2587 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2591 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);
2592 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2594 R_SetupShader_SetPermutationGLSL(mode, permutation);
2595 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2596 if (mode == SHADERMODE_LIGHTSOURCE)
2598 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2599 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2600 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2601 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2602 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2603 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);
2605 // additive passes are only darkened by fog, not tinted
2606 if (r_glsl_permutation->loc_FogColor >= 0)
2607 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2608 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2612 if (mode == SHADERMODE_FLATCOLOR)
2614 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2616 else if (mode == SHADERMODE_LIGHTDIRECTION)
2618 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]);
2619 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]);
2620 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2621 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2622 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2623 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]);
2624 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]);
2628 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]);
2629 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]);
2630 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);
2631 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);
2632 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);
2634 // additive passes are only darkened by fog, not tinted
2635 if (r_glsl_permutation->loc_FogColor >= 0)
2637 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2638 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2640 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2642 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);
2643 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]);
2644 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]);
2645 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]);
2646 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]);
2647 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2648 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2649 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2650 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]);
2652 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2653 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2654 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2655 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]);
2656 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]);
2658 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2659 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));
2660 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2661 if (r_glsl_permutation->loc_Color_Pants >= 0)
2663 if (rsurface.texture->pantstexture)
2664 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2666 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2668 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2670 if (rsurface.texture->shirttexture)
2671 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2673 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2675 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]);
2676 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2677 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2678 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2679 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));
2680 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]);
2681 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2682 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);}
2683 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2685 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2686 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2687 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2688 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2689 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2690 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2691 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2692 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2693 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2694 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2695 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2696 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2697 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2698 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2699 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);
2700 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2701 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2702 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2703 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2704 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2705 if (rsurfacepass == RSURFPASS_BACKGROUND)
2707 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);
2708 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);
2709 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);
2713 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);
2715 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2716 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2717 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2718 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2719 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2721 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2722 if (rsurface.rtlight)
2724 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2725 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2728 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2731 case RENDERPATH_GL13:
2732 case RENDERPATH_GL11:
2734 case RENDERPATH_SOFT:
2735 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);
2736 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2737 R_SetupShader_SetPermutationSoft(mode, permutation);
2738 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2739 if (mode == SHADERMODE_LIGHTSOURCE)
2741 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2742 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2743 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2744 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2745 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2746 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2748 // additive passes are only darkened by fog, not tinted
2749 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2750 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2754 if (mode == SHADERMODE_FLATCOLOR)
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2758 else if (mode == SHADERMODE_LIGHTDIRECTION)
2760 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]);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2762 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2763 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2765 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]);
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2772 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);
2773 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);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2776 // additive passes are only darkened by fog, not tinted
2777 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2778 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2781 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);
2782 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2783 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2784 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]);
2785 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]);
2786 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2787 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2788 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2789 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2791 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2792 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2793 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2794 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2795 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]);
2797 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2798 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));
2799 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2800 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2802 if (rsurface.texture->pantstexture)
2803 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2805 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2807 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2809 if (rsurface.texture->shirttexture)
2810 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2812 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2814 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2815 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2816 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2817 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2818 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));
2819 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2820 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2822 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2823 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2824 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2825 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2826 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2827 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2828 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2829 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2830 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2831 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2832 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2833 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2834 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2835 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2836 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2837 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2838 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2839 if (rsurfacepass == RSURFPASS_BACKGROUND)
2841 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2842 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2843 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2847 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2849 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2850 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2851 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2852 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2853 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2855 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2856 if (rsurface.rtlight)
2858 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2859 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2866 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2868 // select a permutation of the lighting shader appropriate to this
2869 // combination of texture, entity, light source, and fogging, only use the
2870 // minimum features necessary to avoid wasting rendering time in the
2871 // fragment shader on features that are not being used
2872 unsigned int permutation = 0;
2873 unsigned int mode = 0;
2874 const float *lightcolorbase = rtlight->currentcolor;
2875 float ambientscale = rtlight->ambientscale;
2876 float diffusescale = rtlight->diffusescale;
2877 float specularscale = rtlight->specularscale;
2878 // this is the location of the light in view space
2879 vec3_t viewlightorigin;
2880 // this transforms from view space (camera) to light space (cubemap)
2881 matrix4x4_t viewtolight;
2882 matrix4x4_t lighttoview;
2883 float viewtolight16f[16];
2884 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2886 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2887 if (rtlight->currentcubemap != r_texture_whitecube)
2888 permutation |= SHADERPERMUTATION_CUBEFILTER;
2889 if (diffusescale > 0)
2890 permutation |= SHADERPERMUTATION_DIFFUSE;
2891 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2892 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2893 if (r_shadow_usingshadowmap2d)
2895 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2896 if (r_shadow_shadowmapvsdct)
2897 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2899 if (r_shadow_shadowmapsampler)
2900 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2901 if (r_shadow_shadowmappcf > 1)
2902 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2903 else if (r_shadow_shadowmappcf)
2904 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2906 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2907 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2908 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2909 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2910 switch(vid.renderpath)
2912 case RENDERPATH_D3D9:
2914 R_SetupShader_SetPermutationHLSL(mode, permutation);
2915 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2916 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2917 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2918 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2919 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2920 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2921 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2922 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2923 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2924 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2926 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2927 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2928 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2929 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2930 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2931 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2934 case RENDERPATH_D3D10:
2935 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2937 case RENDERPATH_D3D11:
2938 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2940 case RENDERPATH_GL20:
2941 case RENDERPATH_GLES2:
2942 R_SetupShader_SetPermutationGLSL(mode, permutation);
2943 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2944 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2945 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);
2946 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);
2947 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);
2948 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]);
2949 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]);
2950 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));
2951 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]);
2952 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2954 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2955 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2956 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2957 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2958 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2959 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2961 case RENDERPATH_GL13:
2962 case RENDERPATH_GL11:
2964 case RENDERPATH_SOFT:
2965 R_SetupShader_SetPermutationGLSL(mode, permutation);
2966 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2967 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2968 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2969 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2970 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2971 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2972 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]);
2973 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));
2974 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2975 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2977 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2978 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2979 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2980 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2981 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2982 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2987 #define SKINFRAME_HASH 1024
2991 int loadsequence; // incremented each level change
2992 memexpandablearray_t array;
2993 skinframe_t *hash[SKINFRAME_HASH];
2996 r_skinframe_t r_skinframe;
2998 void R_SkinFrame_PrepareForPurge(void)
3000 r_skinframe.loadsequence++;
3001 // wrap it without hitting zero
3002 if (r_skinframe.loadsequence >= 200)
3003 r_skinframe.loadsequence = 1;
3006 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3010 // mark the skinframe as used for the purging code
3011 skinframe->loadsequence = r_skinframe.loadsequence;
3014 void R_SkinFrame_Purge(void)
3018 for (i = 0;i < SKINFRAME_HASH;i++)
3020 for (s = r_skinframe.hash[i];s;s = s->next)
3022 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3024 if (s->merged == s->base)
3026 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3027 R_PurgeTexture(s->stain );s->stain = NULL;
3028 R_PurgeTexture(s->merged);s->merged = NULL;
3029 R_PurgeTexture(s->base );s->base = NULL;
3030 R_PurgeTexture(s->pants );s->pants = NULL;
3031 R_PurgeTexture(s->shirt );s->shirt = NULL;
3032 R_PurgeTexture(s->nmap );s->nmap = NULL;
3033 R_PurgeTexture(s->gloss );s->gloss = NULL;
3034 R_PurgeTexture(s->glow );s->glow = NULL;
3035 R_PurgeTexture(s->fog );s->fog = NULL;
3036 R_PurgeTexture(s->reflect);s->reflect = NULL;
3037 s->loadsequence = 0;
3043 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3045 char basename[MAX_QPATH];
3047 Image_StripImageExtension(name, basename, sizeof(basename));
3049 if( last == NULL ) {
3051 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3052 item = r_skinframe.hash[hashindex];
3057 // linearly search through the hash bucket
3058 for( ; item ; item = item->next ) {
3059 if( !strcmp( item->basename, basename ) ) {
3066 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3070 char basename[MAX_QPATH];
3072 Image_StripImageExtension(name, basename, sizeof(basename));
3074 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3075 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3076 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3080 rtexture_t *dyntexture;
3081 // check whether its a dynamic texture
3082 dyntexture = CL_GetDynTexture( basename );
3083 if (!add && !dyntexture)
3085 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3086 memset(item, 0, sizeof(*item));
3087 strlcpy(item->basename, basename, sizeof(item->basename));
3088 item->base = dyntexture; // either NULL or dyntexture handle
3089 item->textureflags = textureflags;
3090 item->comparewidth = comparewidth;
3091 item->compareheight = compareheight;
3092 item->comparecrc = comparecrc;
3093 item->next = r_skinframe.hash[hashindex];
3094 r_skinframe.hash[hashindex] = item;
3096 else if( item->base == NULL )
3098 rtexture_t *dyntexture;
3099 // check whether its a dynamic texture
3100 // 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]
3101 dyntexture = CL_GetDynTexture( basename );
3102 item->base = dyntexture; // either NULL or dyntexture handle
3105 R_SkinFrame_MarkUsed(item);
3109 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3111 unsigned long long avgcolor[5], wsum; \
3119 for(pix = 0; pix < cnt; ++pix) \
3122 for(comp = 0; comp < 3; ++comp) \
3124 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3127 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3129 for(comp = 0; comp < 3; ++comp) \
3130 avgcolor[comp] += getpixel * w; \
3133 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3134 avgcolor[4] += getpixel; \
3136 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3138 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3139 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3140 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3141 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3144 extern cvar_t gl_picmip;
3145 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3148 unsigned char *pixels;
3149 unsigned char *bumppixels;
3150 unsigned char *basepixels = NULL;
3151 int basepixels_width = 0;
3152 int basepixels_height = 0;
3153 skinframe_t *skinframe;
3154 rtexture_t *ddsbase = NULL;
3155 qboolean ddshasalpha = false;
3156 float ddsavgcolor[4];
3157 char basename[MAX_QPATH];
3158 int miplevel = R_PicmipForFlags(textureflags);
3159 int savemiplevel = miplevel;
3162 if (cls.state == ca_dedicated)
3165 // return an existing skinframe if already loaded
3166 // if loading of the first image fails, don't make a new skinframe as it
3167 // would cause all future lookups of this to be missing
3168 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3169 if (skinframe && skinframe->base)
3172 Image_StripImageExtension(name, basename, sizeof(basename));
3174 // check for DDS texture file first
3175 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3177 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3178 if (basepixels == NULL)
3182 // FIXME handle miplevel
3184 if (developer_loading.integer)
3185 Con_Printf("loading skin \"%s\"\n", name);
3187 // we've got some pixels to store, so really allocate this new texture now
3189 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3190 skinframe->stain = NULL;
3191 skinframe->merged = NULL;
3192 skinframe->base = NULL;
3193 skinframe->pants = NULL;
3194 skinframe->shirt = NULL;
3195 skinframe->nmap = NULL;
3196 skinframe->gloss = NULL;
3197 skinframe->glow = NULL;
3198 skinframe->fog = NULL;
3199 skinframe->reflect = NULL;
3200 skinframe->hasalpha = false;
3204 skinframe->base = ddsbase;
3205 skinframe->hasalpha = ddshasalpha;
3206 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3207 if (r_loadfog && skinframe->hasalpha)
3208 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3209 //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]);
3213 basepixels_width = image_width;
3214 basepixels_height = image_height;
3215 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);
3216 if (textureflags & TEXF_ALPHA)
3218 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3220 if (basepixels[j] < 255)
3222 skinframe->hasalpha = true;
3226 if (r_loadfog && skinframe->hasalpha)
3228 // has transparent pixels
3229 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3230 for (j = 0;j < image_width * image_height * 4;j += 4)
3235 pixels[j+3] = basepixels[j+3];
3237 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);
3241 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3242 //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]);
3243 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3244 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3245 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3246 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3251 mymiplevel = savemiplevel;
3252 if (r_loadnormalmap)
3253 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);
3254 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3256 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3257 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3258 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3259 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3262 // _norm is the name used by tenebrae and has been adopted as standard
3263 if (r_loadnormalmap && skinframe->nmap == NULL)
3265 mymiplevel = savemiplevel;
3266 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3268 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 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3274 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3275 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3276 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);
3278 Mem_Free(bumppixels);
3280 else if (r_shadow_bumpscale_basetexture.value > 0)
3282 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3283 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3284 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);
3287 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3288 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3291 // _luma is supported only for tenebrae compatibility
3292 // _glow is the preferred name
3293 mymiplevel = savemiplevel;
3294 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))))
3296 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);
3297 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3298 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3299 Mem_Free(pixels);pixels = NULL;
3302 mymiplevel = savemiplevel;
3303 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3305 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);
3306 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3307 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3312 mymiplevel = savemiplevel;
3313 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3315 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);
3316 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3317 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3322 mymiplevel = savemiplevel;
3323 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3325 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);
3326 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3327 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3332 mymiplevel = savemiplevel;
3333 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3335 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);
3336 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3337 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3343 Mem_Free(basepixels);
3348 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3349 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3352 unsigned char *temp1, *temp2;
3353 skinframe_t *skinframe;
3355 if (cls.state == ca_dedicated)
3358 // if already loaded just return it, otherwise make a new skinframe
3359 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3360 if (skinframe && skinframe->base)
3363 skinframe->stain = NULL;
3364 skinframe->merged = NULL;
3365 skinframe->base = NULL;
3366 skinframe->pants = NULL;
3367 skinframe->shirt = NULL;
3368 skinframe->nmap = NULL;
3369 skinframe->gloss = NULL;
3370 skinframe->glow = NULL;
3371 skinframe->fog = NULL;
3372 skinframe->reflect = NULL;
3373 skinframe->hasalpha = false;
3375 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3379 if (developer_loading.integer)
3380 Con_Printf("loading 32bit skin \"%s\"\n", name);
3382 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3384 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3385 temp2 = temp1 + width * height * 4;
3386 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3387 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);
3390 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3391 if (textureflags & TEXF_ALPHA)
3393 for (i = 3;i < width * height * 4;i += 4)
3395 if (skindata[i] < 255)
3397 skinframe->hasalpha = true;
3401 if (r_loadfog && skinframe->hasalpha)
3403 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3404 memcpy(fogpixels, skindata, width * height * 4);
3405 for (i = 0;i < width * height * 4;i += 4)
3406 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3407 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3408 Mem_Free(fogpixels);
3412 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3413 //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]);
3418 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3422 skinframe_t *skinframe;
3424 if (cls.state == ca_dedicated)
3427 // if already loaded just return it, otherwise make a new skinframe
3428 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3429 if (skinframe && skinframe->base)
3432 skinframe->stain = NULL;
3433 skinframe->merged = NULL;
3434 skinframe->base = NULL;
3435 skinframe->pants = NULL;
3436 skinframe->shirt = NULL;
3437 skinframe->nmap = NULL;
3438 skinframe->gloss = NULL;
3439 skinframe->glow = NULL;
3440 skinframe->fog = NULL;
3441 skinframe->reflect = NULL;
3442 skinframe->hasalpha = false;
3444 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3448 if (developer_loading.integer)
3449 Con_Printf("loading quake skin \"%s\"\n", name);
3451 // 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)
3452 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3453 memcpy(skinframe->qpixels, skindata, width*height);
3454 skinframe->qwidth = width;
3455 skinframe->qheight = height;
3458 for (i = 0;i < width * height;i++)
3459 featuresmask |= palette_featureflags[skindata[i]];
3461 skinframe->hasalpha = false;
3462 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3463 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3464 skinframe->qgeneratemerged = true;
3465 skinframe->qgeneratebase = skinframe->qhascolormapping;
3466 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3468 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3469 //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]);
3474 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3478 unsigned char *skindata;
3480 if (!skinframe->qpixels)
3483 if (!skinframe->qhascolormapping)
3484 colormapped = false;
3488 if (!skinframe->qgeneratebase)
3493 if (!skinframe->qgeneratemerged)
3497 width = skinframe->qwidth;
3498 height = skinframe->qheight;
3499 skindata = skinframe->qpixels;
3501 if (skinframe->qgeneratenmap)
3503 unsigned char *temp1, *temp2;
3504 skinframe->qgeneratenmap = false;
3505 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3506 temp2 = temp1 + width * height * 4;
3507 // use either a custom palette or the quake palette
3508 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3509 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3510 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);
3514 if (skinframe->qgenerateglow)
3516 skinframe->qgenerateglow = false;
3517 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3522 skinframe->qgeneratebase = false;
3523 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);
3524 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3525 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3529 skinframe->qgeneratemerged = false;
3530 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);
3533 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3535 Mem_Free(skinframe->qpixels);
3536 skinframe->qpixels = NULL;
3540 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)
3543 skinframe_t *skinframe;
3545 if (cls.state == ca_dedicated)
3548 // if already loaded just return it, otherwise make a new skinframe
3549 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3550 if (skinframe && skinframe->base)
3553 skinframe->stain = NULL;
3554 skinframe->merged = NULL;
3555 skinframe->base = NULL;
3556 skinframe->pants = NULL;
3557 skinframe->shirt = NULL;
3558 skinframe->nmap = NULL;
3559 skinframe->gloss = NULL;
3560 skinframe->glow = NULL;
3561 skinframe->fog = NULL;
3562 skinframe->reflect = NULL;
3563 skinframe->hasalpha = false;
3565 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3569 if (developer_loading.integer)
3570 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3572 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3573 if (textureflags & TEXF_ALPHA)
3575 for (i = 0;i < width * height;i++)
3577 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3579 skinframe->hasalpha = true;
3583 if (r_loadfog && skinframe->hasalpha)
3584 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3587 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3588 //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]);
3593 skinframe_t *R_SkinFrame_LoadMissing(void)
3595 skinframe_t *skinframe;
3597 if (cls.state == ca_dedicated)
3600 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3601 skinframe->stain = NULL;
3602 skinframe->merged = NULL;
3603 skinframe->base = NULL;
3604 skinframe->pants = NULL;
3605 skinframe->shirt = NULL;
3606 skinframe->nmap = NULL;
3607 skinframe->gloss = NULL;
3608 skinframe->glow = NULL;
3609 skinframe->fog = NULL;
3610 skinframe->reflect = NULL;
3611 skinframe->hasalpha = false;
3613 skinframe->avgcolor[0] = rand() / RAND_MAX;
3614 skinframe->avgcolor[1] = rand() / RAND_MAX;
3615 skinframe->avgcolor[2] = rand() / RAND_MAX;
3616 skinframe->avgcolor[3] = 1;
3621 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3622 typedef struct suffixinfo_s
3625 qboolean flipx, flipy, flipdiagonal;
3628 static suffixinfo_t suffix[3][6] =
3631 {"px", false, false, false},
3632 {"nx", false, false, false},
3633 {"py", false, false, false},
3634 {"ny", false, false, false},
3635 {"pz", false, false, false},
3636 {"nz", false, false, false}
3639 {"posx", false, false, false},
3640 {"negx", false, false, false},
3641 {"posy", false, false, false},
3642 {"negy", false, false, false},
3643 {"posz", false, false, false},
3644 {"negz", false, false, false}
3647 {"rt", true, false, true},
3648 {"lf", false, true, true},
3649 {"ft", true, true, false},
3650 {"bk", false, false, false},
3651 {"up", true, false, true},
3652 {"dn", true, false, true}
3656 static int componentorder[4] = {0, 1, 2, 3};
3658 rtexture_t *R_LoadCubemap(const char *basename)
3660 int i, j, cubemapsize;
3661 unsigned char *cubemappixels, *image_buffer;
3662 rtexture_t *cubemaptexture;
3664 // must start 0 so the first loadimagepixels has no requested width/height
3666 cubemappixels = NULL;
3667 cubemaptexture = NULL;
3668 // keep trying different suffix groups (posx, px, rt) until one loads
3669 for (j = 0;j < 3 && !cubemappixels;j++)
3671 // load the 6 images in the suffix group
3672 for (i = 0;i < 6;i++)
3674 // generate an image name based on the base and and suffix
3675 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3677 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3679 // an image loaded, make sure width and height are equal
3680 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3682 // if this is the first image to load successfully, allocate the cubemap memory
3683 if (!cubemappixels && image_width >= 1)
3685 cubemapsize = image_width;
3686 // note this clears to black, so unavailable sides are black
3687 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3689 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3691 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);
3694 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3696 Mem_Free(image_buffer);
3700 // if a cubemap loaded, upload it
3703 if (developer_loading.integer)
3704 Con_Printf("loading cubemap \"%s\"\n", basename);
3706 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3707 Mem_Free(cubemappixels);
3711 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3712 if (developer_loading.integer)
3714 Con_Printf("(tried tried images ");
3715 for (j = 0;j < 3;j++)
3716 for (i = 0;i < 6;i++)
3717 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3718 Con_Print(" and was unable to find any of them).\n");
3721 return cubemaptexture;
3724 rtexture_t *R_GetCubemap(const char *basename)
3727 for (i = 0;i < r_texture_numcubemaps;i++)
3728 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3729 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3730 if (i >= MAX_CUBEMAPS)
3731 return r_texture_whitecube;
3732 r_texture_numcubemaps++;
3733 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3734 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3735 return r_texture_cubemaps[i].texture;
3738 void R_FreeCubemaps(void)
3741 for (i = 0;i < r_texture_numcubemaps;i++)
3743 if (developer_loading.integer)
3744 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3745 if (r_texture_cubemaps[i].texture)
3746 R_FreeTexture(r_texture_cubemaps[i].texture);
3748 r_texture_numcubemaps = 0;
3751 void R_Main_FreeViewCache(void)
3753 if (r_refdef.viewcache.entityvisible)
3754 Mem_Free(r_refdef.viewcache.entityvisible);
3755 if (r_refdef.viewcache.world_pvsbits)
3756 Mem_Free(r_refdef.viewcache.world_pvsbits);
3757 if (r_refdef.viewcache.world_leafvisible)
3758 Mem_Free(r_refdef.viewcache.world_leafvisible);
3759 if (r_refdef.viewcache.world_surfacevisible)
3760 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3761 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3764 void R_Main_ResizeViewCache(void)
3766 int numentities = r_refdef.scene.numentities;
3767 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3768 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3769 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3770 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3771 if (r_refdef.viewcache.maxentities < numentities)
3773 r_refdef.viewcache.maxentities = numentities;
3774 if (r_refdef.viewcache.entityvisible)
3775 Mem_Free(r_refdef.viewcache.entityvisible);
3776 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3778 if (r_refdef.viewcache.world_numclusters != numclusters)
3780 r_refdef.viewcache.world_numclusters = numclusters;
3781 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3782 if (r_refdef.viewcache.world_pvsbits)
3783 Mem_Free(r_refdef.viewcache.world_pvsbits);
3784 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3786 if (r_refdef.viewcache.world_numleafs != numleafs)
3788 r_refdef.viewcache.world_numleafs = numleafs;
3789 if (r_refdef.viewcache.world_leafvisible)
3790 Mem_Free(r_refdef.viewcache.world_leafvisible);
3791 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3793 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3795 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3796 if (r_refdef.viewcache.world_surfacevisible)
3797 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3798 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3802 extern rtexture_t *loadingscreentexture;
3803 void gl_main_start(void)
3805 loadingscreentexture = NULL;
3806 r_texture_blanknormalmap = NULL;
3807 r_texture_white = NULL;
3808 r_texture_grey128 = NULL;
3809 r_texture_black = NULL;
3810 r_texture_whitecube = NULL;
3811 r_texture_normalizationcube = NULL;
3812 r_texture_fogattenuation = NULL;
3813 r_texture_fogheighttexture = NULL;
3814 r_texture_gammaramps = NULL;
3815 r_texture_numcubemaps = 0;
3817 r_loaddds = r_texture_dds_load.integer != 0;
3818 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3820 switch(vid.renderpath)
3822 case RENDERPATH_GL20:
3823 case RENDERPATH_D3D9:
3824 case RENDERPATH_D3D10:
3825 case RENDERPATH_D3D11:
3826 case RENDERPATH_SOFT:
3827 case RENDERPATH_GLES2:
3828 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3829 Cvar_SetValueQuick(&gl_combine, 1);
3830 Cvar_SetValueQuick(&r_glsl, 1);
3831 r_loadnormalmap = true;
3835 case RENDERPATH_GL13:
3836 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3837 Cvar_SetValueQuick(&gl_combine, 1);
3838 Cvar_SetValueQuick(&r_glsl, 0);
3839 r_loadnormalmap = false;
3840 r_loadgloss = false;
3843 case RENDERPATH_GL11:
3844 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3845 Cvar_SetValueQuick(&gl_combine, 0);
3846 Cvar_SetValueQuick(&r_glsl, 0);
3847 r_loadnormalmap = false;
3848 r_loadgloss = false;
3854 R_FrameData_Reset();
3858 memset(r_queries, 0, sizeof(r_queries));
3860 r_qwskincache = NULL;
3861 r_qwskincache_size = 0;
3863 // due to caching of texture_t references, the collision cache must be reset
3864 Collision_Cache_Reset(true);
3866 // set up r_skinframe loading system for textures
3867 memset(&r_skinframe, 0, sizeof(r_skinframe));
3868 r_skinframe.loadsequence = 1;
3869 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3871 r_main_texturepool = R_AllocTexturePool();
3872 R_BuildBlankTextures();
3874 if (vid.support.arb_texture_cube_map)
3877 R_BuildNormalizationCube();
3879 r_texture_fogattenuation = NULL;
3880 r_texture_fogheighttexture = NULL;
3881 r_texture_gammaramps = NULL;
3882 //r_texture_fogintensity = NULL;
3883 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3884 memset(&r_waterstate, 0, sizeof(r_waterstate));
3885 r_glsl_permutation = NULL;
3886 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3887 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3888 glslshaderstring = NULL;
3890 r_hlsl_permutation = NULL;
3891 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3892 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3894 hlslshaderstring = NULL;
3895 memset(&r_svbsp, 0, sizeof (r_svbsp));
3897 r_refdef.fogmasktable_density = 0;
3900 void gl_main_shutdown(void)
3903 R_FrameData_Reset();
3905 R_Main_FreeViewCache();
3907 switch(vid.renderpath)
3909 case RENDERPATH_GL11:
3910 case RENDERPATH_GL13:
3911 case RENDERPATH_GL20:
3912 case RENDERPATH_GLES2:
3914 qglDeleteQueriesARB(r_maxqueries, r_queries);
3916 case RENDERPATH_D3D9:
3917 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3919 case RENDERPATH_D3D10:
3920 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3922 case RENDERPATH_D3D11:
3923 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3925 case RENDERPATH_SOFT:
3931 memset(r_queries, 0, sizeof(r_queries));
3933 r_qwskincache = NULL;
3934 r_qwskincache_size = 0;
3936 // clear out the r_skinframe state
3937 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3938 memset(&r_skinframe, 0, sizeof(r_skinframe));
3941 Mem_Free(r_svbsp.nodes);
3942 memset(&r_svbsp, 0, sizeof (r_svbsp));
3943 R_FreeTexturePool(&r_main_texturepool);
3944 loadingscreentexture = NULL;
3945 r_texture_blanknormalmap = NULL;
3946 r_texture_white = NULL;
3947 r_texture_grey128 = NULL;
3948 r_texture_black = NULL;
3949 r_texture_whitecube = NULL;
3950 r_texture_normalizationcube = NULL;
3951 r_texture_fogattenuation = NULL;
3952 r_texture_fogheighttexture = NULL;
3953 r_texture_gammaramps = NULL;
3954 r_texture_numcubemaps = 0;
3955 //r_texture_fogintensity = NULL;
3956 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3957 memset(&r_waterstate, 0, sizeof(r_waterstate));
3960 r_glsl_permutation = NULL;
3961 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3962 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3963 glslshaderstring = NULL;
3965 r_hlsl_permutation = NULL;
3966 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3967 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3969 hlslshaderstring = NULL;
3972 extern void CL_ParseEntityLump(char *entitystring);
3973 void gl_main_newmap(void)
3975 // FIXME: move this code to client
3976 char *entities, entname[MAX_QPATH];
3978 Mem_Free(r_qwskincache);
3979 r_qwskincache = NULL;
3980 r_qwskincache_size = 0;
3983 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3984 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3986 CL_ParseEntityLump(entities);
3990 if (cl.worldmodel->brush.entities)
3991 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3993 R_Main_FreeViewCache();
3995 R_FrameData_Reset();
3998 void GL_Main_Init(void)
4000 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4002 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4003 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4004 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4005 if (gamemode == GAME_NEHAHRA)
4007 Cvar_RegisterVariable (&gl_fogenable);
4008 Cvar_RegisterVariable (&gl_fogdensity);
4009 Cvar_RegisterVariable (&gl_fogred);
4010 Cvar_RegisterVariable (&gl_foggreen);
4011 Cvar_RegisterVariable (&gl_fogblue);
4012 Cvar_RegisterVariable (&gl_fogstart);
4013 Cvar_RegisterVariable (&gl_fogend);
4014 Cvar_RegisterVariable (&gl_skyclip);
4016 Cvar_RegisterVariable(&r_motionblur);
4017 Cvar_RegisterVariable(&r_motionblur_maxblur);
4018 Cvar_RegisterVariable(&r_motionblur_bmin);
4019 Cvar_RegisterVariable(&r_motionblur_vmin);
4020 Cvar_RegisterVariable(&r_motionblur_vmax);
4021 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4022 Cvar_RegisterVariable(&r_motionblur_randomize);
4023 Cvar_RegisterVariable(&r_damageblur);
4024 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4025 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4026 Cvar_RegisterVariable(&r_equalize_entities_by);
4027 Cvar_RegisterVariable(&r_equalize_entities_to);
4028 Cvar_RegisterVariable(&r_depthfirst);
4029 Cvar_RegisterVariable(&r_useinfinitefarclip);
4030 Cvar_RegisterVariable(&r_farclip_base);
4031 Cvar_RegisterVariable(&r_farclip_world);
4032 Cvar_RegisterVariable(&r_nearclip);
4033 Cvar_RegisterVariable(&r_showbboxes);
4034 Cvar_RegisterVariable(&r_showsurfaces);
4035 Cvar_RegisterVariable(&r_showtris);
4036 Cvar_RegisterVariable(&r_shownormals);
4037 Cvar_RegisterVariable(&r_showlighting);
4038 Cvar_RegisterVariable(&r_showshadowvolumes);
4039 Cvar_RegisterVariable(&r_showcollisionbrushes);
4040 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4041 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4042 Cvar_RegisterVariable(&r_showdisabledepthtest);
4043 Cvar_RegisterVariable(&r_drawportals);
4044 Cvar_RegisterVariable(&r_drawentities);
4045 Cvar_RegisterVariable(&r_draw2d);
4046 Cvar_RegisterVariable(&r_drawworld);
4047 Cvar_RegisterVariable(&r_cullentities_trace);
4048 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4049 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4050 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4051 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4052 Cvar_RegisterVariable(&r_drawviewmodel);
4053 Cvar_RegisterVariable(&r_drawexteriormodel);
4054 Cvar_RegisterVariable(&r_speeds);
4055 Cvar_RegisterVariable(&r_fullbrights);
4056 Cvar_RegisterVariable(&r_wateralpha);
4057 Cvar_RegisterVariable(&r_dynamic);
4058 Cvar_RegisterVariable(&r_fakelight);
4059 Cvar_RegisterVariable(&r_fakelight_intensity);
4060 Cvar_RegisterVariable(&r_fullbright);
4061 Cvar_RegisterVariable(&r_shadows);
4062 Cvar_RegisterVariable(&r_shadows_darken);
4063 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4064 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4065 Cvar_RegisterVariable(&r_shadows_throwdistance);
4066 Cvar_RegisterVariable(&r_shadows_throwdirection);
4067 Cvar_RegisterVariable(&r_shadows_focus);
4068 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4069 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4070 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4071 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4072 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4073 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4074 Cvar_RegisterVariable(&r_fog_exp2);
4075 Cvar_RegisterVariable(&r_fog_clear);
4076 Cvar_RegisterVariable(&r_drawfog);
4077 Cvar_RegisterVariable(&r_transparentdepthmasking);
4078 Cvar_RegisterVariable(&r_texture_dds_load);
4079 Cvar_RegisterVariable(&r_texture_dds_save);
4080 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4081 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4082 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4083 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4084 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4085 Cvar_RegisterVariable(&r_textureunits);
4086 Cvar_RegisterVariable(&gl_combine);
4087 Cvar_RegisterVariable(&r_glsl);
4088 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4089 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4090 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4091 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4092 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4093 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4094 Cvar_RegisterVariable(&r_glsl_postprocess);
4095 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4096 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4097 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4098 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4099 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4100 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4101 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4102 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4104 Cvar_RegisterVariable(&r_water);
4105 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4106 Cvar_RegisterVariable(&r_water_clippingplanebias);
4107 Cvar_RegisterVariable(&r_water_refractdistort);
4108 Cvar_RegisterVariable(&r_water_reflectdistort);
4109 Cvar_RegisterVariable(&r_water_scissormode);
4110 Cvar_RegisterVariable(&r_lerpsprites);
4111 Cvar_RegisterVariable(&r_lerpmodels);
4112 Cvar_RegisterVariable(&r_lerplightstyles);
4113 Cvar_RegisterVariable(&r_waterscroll);
4114 Cvar_RegisterVariable(&r_bloom);
4115 Cvar_RegisterVariable(&r_bloom_colorscale);
4116 Cvar_RegisterVariable(&r_bloom_brighten);
4117 Cvar_RegisterVariable(&r_bloom_blur);
4118 Cvar_RegisterVariable(&r_bloom_resolution);
4119 Cvar_RegisterVariable(&r_bloom_colorexponent);
4120 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4121 Cvar_RegisterVariable(&r_hdr);
4122 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4123 Cvar_RegisterVariable(&r_hdr_glowintensity);
4124 Cvar_RegisterVariable(&r_hdr_range);
4125 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4126 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4127 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4128 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4129 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4130 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4131 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4132 Cvar_RegisterVariable(&developer_texturelogging);
4133 Cvar_RegisterVariable(&gl_lightmaps);
4134 Cvar_RegisterVariable(&r_test);
4135 Cvar_RegisterVariable(&r_glsl_saturation);
4136 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4137 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
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_LightPoint(ent->modellight_ambient, 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)
9204 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9205 rsurface.passcolor4f_vertexbuffer = 0;
9206 rsurface.passcolor4f_bufferoffset = 0;
9208 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9210 f = 1 - RSurf_FogVertex(v);
9218 void RSurf_SetupDepthAndCulling(void)
9220 // submodels are biased to avoid z-fighting with world surfaces that they
9221 // may be exactly overlapping (avoids z-fighting artifacts on certain
9222 // doors and things in Quake maps)
9223 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9224 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9225 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9226 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9229 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9231 // transparent sky would be ridiculous
9232 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9234 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9235 skyrenderlater = true;
9236 RSurf_SetupDepthAndCulling();
9238 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9239 // skymasking on them, and Quake3 never did sky masking (unlike
9240 // software Quake and software Quake2), so disable the sky masking
9241 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9242 // and skymasking also looks very bad when noclipping outside the
9243 // level, so don't use it then either.
9244 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9246 R_Mesh_ResetTextureState();
9247 if (skyrendermasked)
9249 R_SetupShader_DepthOrShadow();
9250 // depth-only (masking)
9251 GL_ColorMask(0,0,0,0);
9252 // just to make sure that braindead drivers don't draw
9253 // anything despite that colormask...
9254 GL_BlendFunc(GL_ZERO, GL_ONE);
9255 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9256 if (rsurface.batchvertex3fbuffer)
9257 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9259 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9263 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9265 GL_BlendFunc(GL_ONE, GL_ZERO);
9266 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9267 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9268 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9271 if (skyrendermasked)
9272 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9274 R_Mesh_ResetTextureState();
9275 GL_Color(1, 1, 1, 1);
9278 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9279 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9280 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9282 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9286 // render screenspace normalmap to texture
9288 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9293 // bind lightmap texture
9295 // water/refraction/reflection/camera surfaces have to be handled specially
9296 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9298 int start, end, startplaneindex;
9299 for (start = 0;start < texturenumsurfaces;start = end)
9301 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9302 if(startplaneindex < 0)
9304 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9305 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9309 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9311 // now that we have a batch using the same planeindex, render it
9312 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9314 // render water or distortion background
9316 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));
9318 // blend surface on top
9319 GL_DepthMask(false);
9320 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9323 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9325 // render surface with reflection texture as input
9326 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9327 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));
9334 // render surface batch normally
9335 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9336 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9340 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9342 // OpenGL 1.3 path - anything not completely ancient
9343 qboolean applycolor;
9346 const texturelayer_t *layer;
9347 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);
9348 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9350 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9353 int layertexrgbscale;
9354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9356 if (layerindex == 0)
9360 GL_AlphaTest(false);
9361 GL_DepthFunc(GL_EQUAL);
9364 GL_DepthMask(layer->depthmask && writedepth);
9365 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9366 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9368 layertexrgbscale = 4;
9369 VectorScale(layer->color, 0.25f, layercolor);
9371 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9373 layertexrgbscale = 2;
9374 VectorScale(layer->color, 0.5f, layercolor);
9378 layertexrgbscale = 1;
9379 VectorScale(layer->color, 1.0f, layercolor);
9381 layercolor[3] = layer->color[3];
9382 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9383 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9384 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9385 switch (layer->type)
9387 case TEXTURELAYERTYPE_LITTEXTURE:
9388 // single-pass lightmapped texture with 2x rgbscale
9389 R_Mesh_TexBind(0, r_texture_white);
9390 R_Mesh_TexMatrix(0, NULL);
9391 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9392 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9393 R_Mesh_TexBind(1, layer->texture);
9394 R_Mesh_TexMatrix(1, &layer->texmatrix);
9395 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9396 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9398 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9399 else if (FAKELIGHT_ENABLED)
9400 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9401 else if (rsurface.uselightmaptexture)
9402 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9404 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9406 case TEXTURELAYERTYPE_TEXTURE:
9407 // singletexture unlit texture with transparency support
9408 R_Mesh_TexBind(0, layer->texture);
9409 R_Mesh_TexMatrix(0, &layer->texmatrix);
9410 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9411 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9412 R_Mesh_TexBind(1, 0);
9413 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9414 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9416 case TEXTURELAYERTYPE_FOG:
9417 // singletexture fogging
9420 R_Mesh_TexBind(0, layer->texture);
9421 R_Mesh_TexMatrix(0, &layer->texmatrix);
9422 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9423 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9427 R_Mesh_TexBind(0, 0);
9428 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9430 R_Mesh_TexBind(1, 0);
9431 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9432 // generate a color array for the fog pass
9433 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9434 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9438 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9441 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9443 GL_DepthFunc(GL_LEQUAL);
9444 GL_AlphaTest(false);
9448 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9450 // OpenGL 1.1 - crusty old voodoo path
9453 const texturelayer_t *layer;
9454 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);
9455 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9457 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9459 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9461 if (layerindex == 0)
9465 GL_AlphaTest(false);
9466 GL_DepthFunc(GL_EQUAL);
9469 GL_DepthMask(layer->depthmask && writedepth);
9470 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9471 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9472 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9473 switch (layer->type)
9475 case TEXTURELAYERTYPE_LITTEXTURE:
9476 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9478 // two-pass lit texture with 2x rgbscale
9479 // first the lightmap pass
9480 R_Mesh_TexBind(0, r_texture_white);
9481 R_Mesh_TexMatrix(0, NULL);
9482 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9483 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9484 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9485 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9486 else if (FAKELIGHT_ENABLED)
9487 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9488 else if (rsurface.uselightmaptexture)
9489 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9491 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9492 // then apply the texture to it
9493 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9494 R_Mesh_TexBind(0, layer->texture);
9495 R_Mesh_TexMatrix(0, &layer->texmatrix);
9496 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9497 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9498 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);
9502 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9503 R_Mesh_TexBind(0, layer->texture);
9504 R_Mesh_TexMatrix(0, &layer->texmatrix);
9505 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9506 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9507 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9508 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);
9510 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);
9513 case TEXTURELAYERTYPE_TEXTURE:
9514 // singletexture unlit texture with transparency support
9515 R_Mesh_TexBind(0, layer->texture);
9516 R_Mesh_TexMatrix(0, &layer->texmatrix);
9517 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9518 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9519 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);
9521 case TEXTURELAYERTYPE_FOG:
9522 // singletexture fogging
9525 R_Mesh_TexBind(0, layer->texture);
9526 R_Mesh_TexMatrix(0, &layer->texmatrix);
9527 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9528 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9532 R_Mesh_TexBind(0, 0);
9533 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9535 // generate a color array for the fog pass
9536 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9537 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9541 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9544 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9546 GL_DepthFunc(GL_LEQUAL);
9547 GL_AlphaTest(false);
9551 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9555 r_vertexgeneric_t *batchvertex;
9558 // R_Mesh_ResetTextureState();
9559 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9561 if(rsurface.texture && rsurface.texture->currentskinframe)
9563 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9564 c[3] *= rsurface.texture->currentalpha;
9574 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9576 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9577 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9578 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9581 // brighten it up (as texture value 127 means "unlit")
9582 c[0] *= 2 * r_refdef.view.colorscale;
9583 c[1] *= 2 * r_refdef.view.colorscale;
9584 c[2] *= 2 * r_refdef.view.colorscale;
9586 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9587 c[3] *= r_wateralpha.value;
9589 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9591 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9592 GL_DepthMask(false);
9594 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9596 GL_BlendFunc(GL_ONE, GL_ONE);
9597 GL_DepthMask(false);
9599 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9601 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9602 GL_DepthMask(false);
9604 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9606 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9607 GL_DepthMask(false);
9611 GL_BlendFunc(GL_ONE, GL_ZERO);
9612 GL_DepthMask(writedepth);
9615 if (r_showsurfaces.integer == 3)
9617 rsurface.passcolor4f = NULL;
9619 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9621 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9623 rsurface.passcolor4f = NULL;
9624 rsurface.passcolor4f_vertexbuffer = 0;
9625 rsurface.passcolor4f_bufferoffset = 0;
9627 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9629 qboolean applycolor = true;
9632 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9634 r_refdef.lightmapintensity = 1;
9635 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9636 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9638 else if (FAKELIGHT_ENABLED)
9640 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9642 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9643 RSurf_DrawBatch_GL11_ApplyFakeLight();
9644 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9648 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9650 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9651 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9652 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9655 if(!rsurface.passcolor4f)
9656 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9658 RSurf_DrawBatch_GL11_ApplyAmbient();
9659 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9660 if(r_refdef.fogenabled)
9661 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9662 RSurf_DrawBatch_GL11_ClampColor();
9664 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9665 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9668 else if (!r_refdef.view.showdebug)
9670 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9671 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9672 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9674 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9675 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9677 R_Mesh_PrepareVertices_Generic_Unlock();
9680 else if (r_showsurfaces.integer == 4)
9682 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9683 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9684 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9686 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9687 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9688 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9690 R_Mesh_PrepareVertices_Generic_Unlock();
9693 else if (r_showsurfaces.integer == 2)
9696 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9697 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9698 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9700 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9701 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9702 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9703 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9704 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9705 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9706 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9708 R_Mesh_PrepareVertices_Generic_Unlock();
9709 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9713 int texturesurfaceindex;
9715 const msurface_t *surface;
9716 float surfacecolor4f[4];
9717 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9718 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9720 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9722 surface = texturesurfacelist[texturesurfaceindex];
9723 k = (int)(((size_t)surface) / sizeof(msurface_t));
9724 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9725 for (j = 0;j < surface->num_vertices;j++)
9727 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9728 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9732 R_Mesh_PrepareVertices_Generic_Unlock();
9737 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9740 RSurf_SetupDepthAndCulling();
9741 if (r_showsurfaces.integer)
9743 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9746 switch (vid.renderpath)
9748 case RENDERPATH_GL20:
9749 case RENDERPATH_D3D9:
9750 case RENDERPATH_D3D10:
9751 case RENDERPATH_D3D11:
9752 case RENDERPATH_SOFT:
9753 case RENDERPATH_GLES2:
9754 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9756 case RENDERPATH_GL13:
9757 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9759 case RENDERPATH_GL11:
9760 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9766 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9769 RSurf_SetupDepthAndCulling();
9770 if (r_showsurfaces.integer)
9772 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9775 switch (vid.renderpath)
9777 case RENDERPATH_GL20:
9778 case RENDERPATH_D3D9:
9779 case RENDERPATH_D3D10:
9780 case RENDERPATH_D3D11:
9781 case RENDERPATH_SOFT:
9782 case RENDERPATH_GLES2:
9783 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9785 case RENDERPATH_GL13:
9786 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9788 case RENDERPATH_GL11:
9789 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9795 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9798 int texturenumsurfaces, endsurface;
9800 const msurface_t *surface;
9801 #define MAXBATCH_TRANSPARENTSURFACES 256
9802 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9804 // if the model is static it doesn't matter what value we give for
9805 // wantnormals and wanttangents, so this logic uses only rules applicable
9806 // to a model, knowing that they are meaningless otherwise
9807 if (ent == r_refdef.scene.worldentity)
9808 RSurf_ActiveWorldEntity();
9809 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9810 RSurf_ActiveModelEntity(ent, false, false, false);
9813 switch (vid.renderpath)
9815 case RENDERPATH_GL20:
9816 case RENDERPATH_D3D9:
9817 case RENDERPATH_D3D10:
9818 case RENDERPATH_D3D11:
9819 case RENDERPATH_SOFT:
9820 case RENDERPATH_GLES2:
9821 RSurf_ActiveModelEntity(ent, true, true, false);
9823 case RENDERPATH_GL13:
9824 case RENDERPATH_GL11:
9825 RSurf_ActiveModelEntity(ent, true, false, false);
9830 if (r_transparentdepthmasking.integer)
9832 qboolean setup = false;
9833 for (i = 0;i < numsurfaces;i = j)
9836 surface = rsurface.modelsurfaces + surfacelist[i];
9837 texture = surface->texture;
9838 rsurface.texture = R_GetCurrentTexture(texture);
9839 rsurface.lightmaptexture = NULL;
9840 rsurface.deluxemaptexture = NULL;
9841 rsurface.uselightmaptexture = false;
9842 // scan ahead until we find a different texture
9843 endsurface = min(i + 1024, numsurfaces);
9844 texturenumsurfaces = 0;
9845 texturesurfacelist[texturenumsurfaces++] = surface;
9846 for (;j < endsurface;j++)
9848 surface = rsurface.modelsurfaces + surfacelist[j];
9849 if (texture != surface->texture)
9851 texturesurfacelist[texturenumsurfaces++] = surface;
9853 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9855 // render the range of surfaces as depth
9859 GL_ColorMask(0,0,0,0);
9862 GL_BlendFunc(GL_ONE, GL_ZERO);
9864 // R_Mesh_ResetTextureState();
9865 R_SetupShader_DepthOrShadow();
9867 RSurf_SetupDepthAndCulling();
9868 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9869 if (rsurface.batchvertex3fbuffer)
9870 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9872 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9876 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9879 for (i = 0;i < numsurfaces;i = j)
9882 surface = rsurface.modelsurfaces + surfacelist[i];
9883 texture = surface->texture;
9884 rsurface.texture = R_GetCurrentTexture(texture);
9885 // scan ahead until we find a different texture
9886 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9887 texturenumsurfaces = 0;
9888 texturesurfacelist[texturenumsurfaces++] = surface;
9889 if(FAKELIGHT_ENABLED)
9891 rsurface.lightmaptexture = NULL;
9892 rsurface.deluxemaptexture = NULL;
9893 rsurface.uselightmaptexture = false;
9894 for (;j < endsurface;j++)
9896 surface = rsurface.modelsurfaces + surfacelist[j];
9897 if (texture != surface->texture)
9899 texturesurfacelist[texturenumsurfaces++] = surface;
9904 rsurface.lightmaptexture = surface->lightmaptexture;
9905 rsurface.deluxemaptexture = surface->deluxemaptexture;
9906 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9907 for (;j < endsurface;j++)
9909 surface = rsurface.modelsurfaces + surfacelist[j];
9910 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9912 texturesurfacelist[texturenumsurfaces++] = surface;
9915 // render the range of surfaces
9916 if (ent == r_refdef.scene.worldentity)
9917 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9919 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9921 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9924 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9926 // transparent surfaces get pushed off into the transparent queue
9927 int surfacelistindex;
9928 const msurface_t *surface;
9929 vec3_t tempcenter, center;
9930 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9932 surface = texturesurfacelist[surfacelistindex];
9933 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9934 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9935 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9936 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9937 if (queueentity->transparent_offset) // transparent offset
9939 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9940 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9941 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9943 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9947 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9949 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9951 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9953 RSurf_SetupDepthAndCulling();
9954 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9955 if (rsurface.batchvertex3fbuffer)
9956 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9958 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9962 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9964 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9967 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9970 if (!rsurface.texture->currentnumlayers)
9972 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9973 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9975 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9977 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9978 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9979 else if (!rsurface.texture->currentnumlayers)
9981 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9983 // in the deferred case, transparent surfaces were queued during prepass
9984 if (!r_shadow_usingdeferredprepass)
9985 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9989 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9990 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9995 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9999 R_FrameData_SetMark();
10000 // break the surface list down into batches by texture and use of lightmapping
10001 for (i = 0;i < numsurfaces;i = j)
10004 // texture is the base texture pointer, rsurface.texture is the
10005 // current frame/skin the texture is directing us to use (for example
10006 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10007 // use skin 1 instead)
10008 texture = surfacelist[i]->texture;
10009 rsurface.texture = R_GetCurrentTexture(texture);
10010 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10012 // if this texture is not the kind we want, skip ahead to the next one
10013 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10017 if(FAKELIGHT_ENABLED || depthonly || prepass)
10019 rsurface.lightmaptexture = NULL;
10020 rsurface.deluxemaptexture = NULL;
10021 rsurface.uselightmaptexture = false;
10022 // simply scan ahead until we find a different texture or lightmap state
10023 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10028 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10029 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10030 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10031 // simply scan ahead until we find a different texture or lightmap state
10032 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10035 // render the range of surfaces
10036 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10038 R_FrameData_ReturnToMark();
10041 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10045 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10048 if (!rsurface.texture->currentnumlayers)
10050 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10051 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10053 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10055 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10056 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10057 else if (!rsurface.texture->currentnumlayers)
10059 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10061 // in the deferred case, transparent surfaces were queued during prepass
10062 if (!r_shadow_usingdeferredprepass)
10063 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10067 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10068 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10073 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10076 texture_t *texture;
10077 R_FrameData_SetMark();
10078 // break the surface list down into batches by texture and use of lightmapping
10079 for (i = 0;i < numsurfaces;i = j)
10082 // texture is the base texture pointer, rsurface.texture is the
10083 // current frame/skin the texture is directing us to use (for example
10084 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10085 // use skin 1 instead)
10086 texture = surfacelist[i]->texture;
10087 rsurface.texture = R_GetCurrentTexture(texture);
10088 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10090 // if this texture is not the kind we want, skip ahead to the next one
10091 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10095 if(FAKELIGHT_ENABLED || depthonly || prepass)
10097 rsurface.lightmaptexture = NULL;
10098 rsurface.deluxemaptexture = NULL;
10099 rsurface.uselightmaptexture = false;
10100 // simply scan ahead until we find a different texture or lightmap state
10101 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10106 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10107 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10108 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10109 // simply scan ahead until we find a different texture or lightmap state
10110 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10113 // render the range of surfaces
10114 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10116 R_FrameData_ReturnToMark();
10119 float locboxvertex3f[6*4*3] =
10121 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10122 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10123 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10124 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10125 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10126 1,0,0, 0,0,0, 0,1,0, 1,1,0
10129 unsigned short locboxelements[6*2*3] =
10134 12,13,14, 12,14,15,
10135 16,17,18, 16,18,19,
10139 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10142 cl_locnode_t *loc = (cl_locnode_t *)ent;
10144 float vertex3f[6*4*3];
10146 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10147 GL_DepthMask(false);
10148 GL_DepthRange(0, 1);
10149 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10150 GL_DepthTest(true);
10151 GL_CullFace(GL_NONE);
10152 R_EntityMatrix(&identitymatrix);
10154 // R_Mesh_ResetTextureState();
10156 i = surfacelist[0];
10157 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10158 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10159 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10160 surfacelist[0] < 0 ? 0.5f : 0.125f);
10162 if (VectorCompare(loc->mins, loc->maxs))
10164 VectorSet(size, 2, 2, 2);
10165 VectorMA(loc->mins, -0.5f, size, mins);
10169 VectorCopy(loc->mins, mins);
10170 VectorSubtract(loc->maxs, loc->mins, size);
10173 for (i = 0;i < 6*4*3;)
10174 for (j = 0;j < 3;j++, i++)
10175 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10177 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10178 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10179 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10182 void R_DrawLocs(void)
10185 cl_locnode_t *loc, *nearestloc;
10187 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10188 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10190 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10191 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10195 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10197 if (decalsystem->decals)
10198 Mem_Free(decalsystem->decals);
10199 memset(decalsystem, 0, sizeof(*decalsystem));
10202 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)
10205 tridecal_t *decals;
10208 // expand or initialize the system
10209 if (decalsystem->maxdecals <= decalsystem->numdecals)
10211 decalsystem_t old = *decalsystem;
10212 qboolean useshortelements;
10213 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10214 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10215 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)));
10216 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10217 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10218 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10219 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10220 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10221 if (decalsystem->numdecals)
10222 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10224 Mem_Free(old.decals);
10225 for (i = 0;i < decalsystem->maxdecals*3;i++)
10226 decalsystem->element3i[i] = i;
10227 if (useshortelements)
10228 for (i = 0;i < decalsystem->maxdecals*3;i++)
10229 decalsystem->element3s[i] = i;
10232 // grab a decal and search for another free slot for the next one
10233 decals = decalsystem->decals;
10234 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10235 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10237 decalsystem->freedecal = i;
10238 if (decalsystem->numdecals <= i)
10239 decalsystem->numdecals = i + 1;
10241 // initialize the decal
10243 decal->triangleindex = triangleindex;
10244 decal->surfaceindex = surfaceindex;
10245 decal->decalsequence = decalsequence;
10246 decal->color4f[0][0] = c0[0];
10247 decal->color4f[0][1] = c0[1];
10248 decal->color4f[0][2] = c0[2];
10249 decal->color4f[0][3] = 1;
10250 decal->color4f[1][0] = c1[0];
10251 decal->color4f[1][1] = c1[1];
10252 decal->color4f[1][2] = c1[2];
10253 decal->color4f[1][3] = 1;
10254 decal->color4f[2][0] = c2[0];
10255 decal->color4f[2][1] = c2[1];
10256 decal->color4f[2][2] = c2[2];
10257 decal->color4f[2][3] = 1;
10258 decal->vertex3f[0][0] = v0[0];
10259 decal->vertex3f[0][1] = v0[1];
10260 decal->vertex3f[0][2] = v0[2];
10261 decal->vertex3f[1][0] = v1[0];
10262 decal->vertex3f[1][1] = v1[1];
10263 decal->vertex3f[1][2] = v1[2];
10264 decal->vertex3f[2][0] = v2[0];
10265 decal->vertex3f[2][1] = v2[1];
10266 decal->vertex3f[2][2] = v2[2];
10267 decal->texcoord2f[0][0] = t0[0];
10268 decal->texcoord2f[0][1] = t0[1];
10269 decal->texcoord2f[1][0] = t1[0];
10270 decal->texcoord2f[1][1] = t1[1];
10271 decal->texcoord2f[2][0] = t2[0];
10272 decal->texcoord2f[2][1] = t2[1];
10275 extern cvar_t cl_decals_bias;
10276 extern cvar_t cl_decals_models;
10277 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10278 // baseparms, parms, temps
10279 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)
10284 const float *vertex3f;
10285 const float *normal3f;
10287 float points[2][9][3];
10294 e = rsurface.modelelement3i + 3*triangleindex;
10296 vertex3f = rsurface.modelvertex3f;
10297 normal3f = rsurface.modelnormal3f;
10301 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10303 index = 3*e[cornerindex];
10304 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10309 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10311 index = 3*e[cornerindex];
10312 VectorCopy(vertex3f + index, v[cornerindex]);
10317 //TriangleNormal(v[0], v[1], v[2], normal);
10318 //if (DotProduct(normal, localnormal) < 0.0f)
10320 // clip by each of the box planes formed from the projection matrix
10321 // if anything survives, we emit the decal
10322 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]);
10325 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]);
10328 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]);
10331 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]);
10334 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]);
10337 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]);
10340 // some part of the triangle survived, so we have to accept it...
10343 // dynamic always uses the original triangle
10345 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10347 index = 3*e[cornerindex];
10348 VectorCopy(vertex3f + index, v[cornerindex]);
10351 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10353 // convert vertex positions to texcoords
10354 Matrix4x4_Transform(projection, v[cornerindex], temp);
10355 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10356 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10357 // calculate distance fade from the projection origin
10358 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10359 f = bound(0.0f, f, 1.0f);
10360 c[cornerindex][0] = r * f;
10361 c[cornerindex][1] = g * f;
10362 c[cornerindex][2] = b * f;
10363 c[cornerindex][3] = 1.0f;
10364 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10367 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);
10369 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10370 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);
10372 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)
10374 matrix4x4_t projection;
10375 decalsystem_t *decalsystem;
10378 const msurface_t *surface;
10379 const msurface_t *surfaces;
10380 const int *surfacelist;
10381 const texture_t *texture;
10383 int numsurfacelist;
10384 int surfacelistindex;
10387 float localorigin[3];
10388 float localnormal[3];
10389 float localmins[3];
10390 float localmaxs[3];
10393 float planes[6][4];
10396 int bih_triangles_count;
10397 int bih_triangles[256];
10398 int bih_surfaces[256];
10400 decalsystem = &ent->decalsystem;
10401 model = ent->model;
10402 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10404 R_DecalSystem_Reset(&ent->decalsystem);
10408 if (!model->brush.data_leafs && !cl_decals_models.integer)
10410 if (decalsystem->model)
10411 R_DecalSystem_Reset(decalsystem);
10415 if (decalsystem->model != model)
10416 R_DecalSystem_Reset(decalsystem);
10417 decalsystem->model = model;
10419 RSurf_ActiveModelEntity(ent, true, false, false);
10421 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10422 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10423 VectorNormalize(localnormal);
10424 localsize = worldsize*rsurface.inversematrixscale;
10425 localmins[0] = localorigin[0] - localsize;
10426 localmins[1] = localorigin[1] - localsize;
10427 localmins[2] = localorigin[2] - localsize;
10428 localmaxs[0] = localorigin[0] + localsize;
10429 localmaxs[1] = localorigin[1] + localsize;
10430 localmaxs[2] = localorigin[2] + localsize;
10432 //VectorCopy(localnormal, planes[4]);
10433 //VectorVectors(planes[4], planes[2], planes[0]);
10434 AnglesFromVectors(angles, localnormal, NULL, false);
10435 AngleVectors(angles, planes[0], planes[2], planes[4]);
10436 VectorNegate(planes[0], planes[1]);
10437 VectorNegate(planes[2], planes[3]);
10438 VectorNegate(planes[4], planes[5]);
10439 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10440 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10441 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10442 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10443 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10444 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10449 matrix4x4_t forwardprojection;
10450 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10451 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10456 float projectionvector[4][3];
10457 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10458 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10459 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10460 projectionvector[0][0] = planes[0][0] * ilocalsize;
10461 projectionvector[0][1] = planes[1][0] * ilocalsize;
10462 projectionvector[0][2] = planes[2][0] * ilocalsize;
10463 projectionvector[1][0] = planes[0][1] * ilocalsize;
10464 projectionvector[1][1] = planes[1][1] * ilocalsize;
10465 projectionvector[1][2] = planes[2][1] * ilocalsize;
10466 projectionvector[2][0] = planes[0][2] * ilocalsize;
10467 projectionvector[2][1] = planes[1][2] * ilocalsize;
10468 projectionvector[2][2] = planes[2][2] * ilocalsize;
10469 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10470 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10471 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10472 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10476 dynamic = model->surfmesh.isanimated;
10477 numsurfacelist = model->nummodelsurfaces;
10478 surfacelist = model->sortedmodelsurfaces;
10479 surfaces = model->data_surfaces;
10482 bih_triangles_count = -1;
10485 if(model->render_bih.numleafs)
10486 bih = &model->render_bih;
10487 else if(model->collision_bih.numleafs)
10488 bih = &model->collision_bih;
10491 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10492 if(bih_triangles_count == 0)
10494 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10496 if(bih_triangles_count > 0)
10498 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10500 surfaceindex = bih_surfaces[triangleindex];
10501 surface = surfaces + surfaceindex;
10502 texture = surface->texture;
10503 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10505 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10507 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10512 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10514 surfaceindex = surfacelist[surfacelistindex];
10515 surface = surfaces + surfaceindex;
10516 // check cull box first because it rejects more than any other check
10517 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10519 // skip transparent surfaces
10520 texture = surface->texture;
10521 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10523 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10525 numtriangles = surface->num_triangles;
10526 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10527 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10532 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10533 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)
10535 int renderentityindex;
10536 float worldmins[3];
10537 float worldmaxs[3];
10538 entity_render_t *ent;
10540 if (!cl_decals_newsystem.integer)
10543 worldmins[0] = worldorigin[0] - worldsize;
10544 worldmins[1] = worldorigin[1] - worldsize;
10545 worldmins[2] = worldorigin[2] - worldsize;
10546 worldmaxs[0] = worldorigin[0] + worldsize;
10547 worldmaxs[1] = worldorigin[1] + worldsize;
10548 worldmaxs[2] = worldorigin[2] + worldsize;
10550 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10552 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10554 ent = r_refdef.scene.entities[renderentityindex];
10555 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10558 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10562 typedef struct r_decalsystem_splatqueue_s
10564 vec3_t worldorigin;
10565 vec3_t worldnormal;
10571 r_decalsystem_splatqueue_t;
10573 int r_decalsystem_numqueued = 0;
10574 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10576 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)
10578 r_decalsystem_splatqueue_t *queue;
10580 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10583 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10584 VectorCopy(worldorigin, queue->worldorigin);
10585 VectorCopy(worldnormal, queue->worldnormal);
10586 Vector4Set(queue->color, r, g, b, a);
10587 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10588 queue->worldsize = worldsize;
10589 queue->decalsequence = cl.decalsequence++;
10592 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10595 r_decalsystem_splatqueue_t *queue;
10597 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10598 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);
10599 r_decalsystem_numqueued = 0;
10602 extern cvar_t cl_decals_max;
10603 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10606 decalsystem_t *decalsystem = &ent->decalsystem;
10613 if (!decalsystem->numdecals)
10616 if (r_showsurfaces.integer)
10619 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10621 R_DecalSystem_Reset(decalsystem);
10625 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10626 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10628 if (decalsystem->lastupdatetime)
10629 frametime = (cl.time - decalsystem->lastupdatetime);
10632 decalsystem->lastupdatetime = cl.time;
10633 decal = decalsystem->decals;
10634 numdecals = decalsystem->numdecals;
10636 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10638 if (decal->color4f[0][3])
10640 decal->lived += frametime;
10641 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10643 memset(decal, 0, sizeof(*decal));
10644 if (decalsystem->freedecal > i)
10645 decalsystem->freedecal = i;
10649 decal = decalsystem->decals;
10650 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10653 // collapse the array by shuffling the tail decals into the gaps
10656 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10657 decalsystem->freedecal++;
10658 if (decalsystem->freedecal == numdecals)
10660 decal[decalsystem->freedecal] = decal[--numdecals];
10663 decalsystem->numdecals = numdecals;
10665 if (numdecals <= 0)
10667 // if there are no decals left, reset decalsystem
10668 R_DecalSystem_Reset(decalsystem);
10672 extern skinframe_t *decalskinframe;
10673 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10676 decalsystem_t *decalsystem = &ent->decalsystem;
10685 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10688 numdecals = decalsystem->numdecals;
10692 if (r_showsurfaces.integer)
10695 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10697 R_DecalSystem_Reset(decalsystem);
10701 // if the model is static it doesn't matter what value we give for
10702 // wantnormals and wanttangents, so this logic uses only rules applicable
10703 // to a model, knowing that they are meaningless otherwise
10704 if (ent == r_refdef.scene.worldentity)
10705 RSurf_ActiveWorldEntity();
10707 RSurf_ActiveModelEntity(ent, false, false, false);
10709 decalsystem->lastupdatetime = cl.time;
10710 decal = decalsystem->decals;
10712 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10714 // update vertex positions for animated models
10715 v3f = decalsystem->vertex3f;
10716 c4f = decalsystem->color4f;
10717 t2f = decalsystem->texcoord2f;
10718 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10720 if (!decal->color4f[0][3])
10723 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10726 // update color values for fading decals
10727 if (decal->lived >= cl_decals_time.value)
10728 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10732 c4f[ 0] = decal->color4f[0][0] * alpha;
10733 c4f[ 1] = decal->color4f[0][1] * alpha;
10734 c4f[ 2] = decal->color4f[0][2] * alpha;
10736 c4f[ 4] = decal->color4f[1][0] * alpha;
10737 c4f[ 5] = decal->color4f[1][1] * alpha;
10738 c4f[ 6] = decal->color4f[1][2] * alpha;
10740 c4f[ 8] = decal->color4f[2][0] * alpha;
10741 c4f[ 9] = decal->color4f[2][1] * alpha;
10742 c4f[10] = decal->color4f[2][2] * alpha;
10745 t2f[0] = decal->texcoord2f[0][0];
10746 t2f[1] = decal->texcoord2f[0][1];
10747 t2f[2] = decal->texcoord2f[1][0];
10748 t2f[3] = decal->texcoord2f[1][1];
10749 t2f[4] = decal->texcoord2f[2][0];
10750 t2f[5] = decal->texcoord2f[2][1];
10752 // update vertex positions for animated models
10753 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10755 e = rsurface.modelelement3i + 3*decal->triangleindex;
10756 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10757 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10758 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10762 VectorCopy(decal->vertex3f[0], v3f);
10763 VectorCopy(decal->vertex3f[1], v3f + 3);
10764 VectorCopy(decal->vertex3f[2], v3f + 6);
10767 if (r_refdef.fogenabled)
10769 alpha = RSurf_FogVertex(v3f);
10770 VectorScale(c4f, alpha, c4f);
10771 alpha = RSurf_FogVertex(v3f + 3);
10772 VectorScale(c4f + 4, alpha, c4f + 4);
10773 alpha = RSurf_FogVertex(v3f + 6);
10774 VectorScale(c4f + 8, alpha, c4f + 8);
10785 r_refdef.stats.drawndecals += numtris;
10787 // now render the decals all at once
10788 // (this assumes they all use one particle font texture!)
10789 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);
10790 // R_Mesh_ResetTextureState();
10791 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10792 GL_DepthMask(false);
10793 GL_DepthRange(0, 1);
10794 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10795 GL_DepthTest(true);
10796 GL_CullFace(GL_NONE);
10797 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10798 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10799 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10803 static void R_DrawModelDecals(void)
10807 // fade faster when there are too many decals
10808 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10809 for (i = 0;i < r_refdef.scene.numentities;i++)
10810 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10812 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10813 for (i = 0;i < r_refdef.scene.numentities;i++)
10814 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10815 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10817 R_DecalSystem_ApplySplatEntitiesQueue();
10819 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10820 for (i = 0;i < r_refdef.scene.numentities;i++)
10821 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10823 r_refdef.stats.totaldecals += numdecals;
10825 if (r_showsurfaces.integer)
10828 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10830 for (i = 0;i < r_refdef.scene.numentities;i++)
10832 if (!r_refdef.viewcache.entityvisible[i])
10834 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10835 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10839 extern cvar_t mod_collision_bih;
10840 void R_DrawDebugModel(void)
10842 entity_render_t *ent = rsurface.entity;
10843 int i, j, k, l, flagsmask;
10844 const msurface_t *surface;
10845 dp_model_t *model = ent->model;
10848 switch(vid.renderpath)
10850 case RENDERPATH_GL11:
10851 case RENDERPATH_GL13:
10852 case RENDERPATH_GL20:
10854 case RENDERPATH_D3D9:
10855 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10857 case RENDERPATH_D3D10:
10858 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10860 case RENDERPATH_D3D11:
10861 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10863 case RENDERPATH_SOFT:
10864 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10866 case RENDERPATH_GLES2:
10867 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10871 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10873 // R_Mesh_ResetTextureState();
10874 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10875 GL_DepthRange(0, 1);
10876 GL_DepthTest(!r_showdisabledepthtest.integer);
10877 GL_DepthMask(false);
10878 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10880 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10884 qboolean cullbox = ent == r_refdef.scene.worldentity;
10885 const q3mbrush_t *brush;
10886 const bih_t *bih = &model->collision_bih;
10887 const bih_leaf_t *bihleaf;
10888 float vertex3f[3][3];
10889 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10891 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10893 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10895 switch (bihleaf->type)
10898 brush = model->brush.data_brushes + bihleaf->itemindex;
10899 if (brush->colbrushf && brush->colbrushf->numtriangles)
10901 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);
10902 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10903 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10906 case BIH_COLLISIONTRIANGLE:
10907 triangleindex = bihleaf->itemindex;
10908 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10909 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10910 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10911 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);
10912 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10913 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10915 case BIH_RENDERTRIANGLE:
10916 triangleindex = bihleaf->itemindex;
10917 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10918 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10919 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10920 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);
10921 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10922 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10928 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10930 if (r_showtris.integer || (r_shownormals.value != 0))
10932 if (r_showdisabledepthtest.integer)
10934 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10935 GL_DepthMask(false);
10939 GL_BlendFunc(GL_ONE, GL_ZERO);
10940 GL_DepthMask(true);
10942 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10944 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10946 rsurface.texture = R_GetCurrentTexture(surface->texture);
10947 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10949 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10950 if (r_showtris.value > 0)
10952 if (!rsurface.texture->currentlayers->depthmask)
10953 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10954 else if (ent == r_refdef.scene.worldentity)
10955 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10957 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10958 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10959 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10961 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10964 if (r_shownormals.value < 0)
10966 qglBegin(GL_LINES);
10967 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10969 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10970 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10971 qglVertex3f(v[0], v[1], v[2]);
10972 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10973 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10974 qglVertex3f(v[0], v[1], v[2]);
10979 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10981 qglBegin(GL_LINES);
10982 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10984 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10985 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10986 qglVertex3f(v[0], v[1], v[2]);
10987 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10988 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10989 qglVertex3f(v[0], v[1], v[2]);
10993 qglBegin(GL_LINES);
10994 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10996 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10997 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10998 qglVertex3f(v[0], v[1], v[2]);
10999 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11000 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11001 qglVertex3f(v[0], v[1], v[2]);
11005 qglBegin(GL_LINES);
11006 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11008 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11009 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11010 qglVertex3f(v[0], v[1], v[2]);
11011 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11012 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11013 qglVertex3f(v[0], v[1], v[2]);
11020 rsurface.texture = NULL;
11024 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11025 int r_maxsurfacelist = 0;
11026 const msurface_t **r_surfacelist = NULL;
11027 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11029 int i, j, endj, flagsmask;
11030 dp_model_t *model = r_refdef.scene.worldmodel;
11031 msurface_t *surfaces;
11032 unsigned char *update;
11033 int numsurfacelist = 0;
11037 if (r_maxsurfacelist < model->num_surfaces)
11039 r_maxsurfacelist = model->num_surfaces;
11041 Mem_Free((msurface_t**)r_surfacelist);
11042 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11045 RSurf_ActiveWorldEntity();
11047 surfaces = model->data_surfaces;
11048 update = model->brushq1.lightmapupdateflags;
11050 // update light styles on this submodel
11051 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11053 model_brush_lightstyleinfo_t *style;
11054 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11056 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11058 int *list = style->surfacelist;
11059 style->value = r_refdef.scene.lightstylevalue[style->style];
11060 for (j = 0;j < style->numsurfaces;j++)
11061 update[list[j]] = true;
11066 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11070 R_DrawDebugModel();
11071 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11075 rsurface.lightmaptexture = NULL;
11076 rsurface.deluxemaptexture = NULL;
11077 rsurface.uselightmaptexture = false;
11078 rsurface.texture = NULL;
11079 rsurface.rtlight = NULL;
11080 numsurfacelist = 0;
11081 // add visible surfaces to draw list
11082 for (i = 0;i < model->nummodelsurfaces;i++)
11084 j = model->sortedmodelsurfaces[i];
11085 if (r_refdef.viewcache.world_surfacevisible[j])
11086 r_surfacelist[numsurfacelist++] = surfaces + j;
11088 // update lightmaps if needed
11089 if (model->brushq1.firstrender)
11091 model->brushq1.firstrender = false;
11092 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11094 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11098 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11099 if (r_refdef.viewcache.world_surfacevisible[j])
11101 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11103 // don't do anything if there were no surfaces
11104 if (!numsurfacelist)
11106 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11109 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11111 // add to stats if desired
11112 if (r_speeds.integer && !skysurfaces && !depthonly)
11114 r_refdef.stats.world_surfaces += numsurfacelist;
11115 for (j = 0;j < numsurfacelist;j++)
11116 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11119 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11122 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11124 int i, j, endj, flagsmask;
11125 dp_model_t *model = ent->model;
11126 msurface_t *surfaces;
11127 unsigned char *update;
11128 int numsurfacelist = 0;
11132 if (r_maxsurfacelist < model->num_surfaces)
11134 r_maxsurfacelist = model->num_surfaces;
11136 Mem_Free((msurface_t **)r_surfacelist);
11137 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11140 // if the model is static it doesn't matter what value we give for
11141 // wantnormals and wanttangents, so this logic uses only rules applicable
11142 // to a model, knowing that they are meaningless otherwise
11143 if (ent == r_refdef.scene.worldentity)
11144 RSurf_ActiveWorldEntity();
11145 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11146 RSurf_ActiveModelEntity(ent, false, false, false);
11148 RSurf_ActiveModelEntity(ent, true, true, true);
11149 else if (depthonly)
11151 switch (vid.renderpath)
11153 case RENDERPATH_GL20:
11154 case RENDERPATH_D3D9:
11155 case RENDERPATH_D3D10:
11156 case RENDERPATH_D3D11:
11157 case RENDERPATH_SOFT:
11158 case RENDERPATH_GLES2:
11159 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11161 case RENDERPATH_GL13:
11162 case RENDERPATH_GL11:
11163 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11169 switch (vid.renderpath)
11171 case RENDERPATH_GL20:
11172 case RENDERPATH_D3D9:
11173 case RENDERPATH_D3D10:
11174 case RENDERPATH_D3D11:
11175 case RENDERPATH_SOFT:
11176 case RENDERPATH_GLES2:
11177 RSurf_ActiveModelEntity(ent, true, true, false);
11179 case RENDERPATH_GL13:
11180 case RENDERPATH_GL11:
11181 RSurf_ActiveModelEntity(ent, true, false, false);
11186 surfaces = model->data_surfaces;
11187 update = model->brushq1.lightmapupdateflags;
11189 // update light styles
11190 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11192 model_brush_lightstyleinfo_t *style;
11193 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11195 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11197 int *list = style->surfacelist;
11198 style->value = r_refdef.scene.lightstylevalue[style->style];
11199 for (j = 0;j < style->numsurfaces;j++)
11200 update[list[j]] = true;
11205 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11209 R_DrawDebugModel();
11210 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11214 rsurface.lightmaptexture = NULL;
11215 rsurface.deluxemaptexture = NULL;
11216 rsurface.uselightmaptexture = false;
11217 rsurface.texture = NULL;
11218 rsurface.rtlight = NULL;
11219 numsurfacelist = 0;
11220 // add visible surfaces to draw list
11221 for (i = 0;i < model->nummodelsurfaces;i++)
11222 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11223 // don't do anything if there were no surfaces
11224 if (!numsurfacelist)
11226 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11229 // update lightmaps if needed
11233 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11238 R_BuildLightMap(ent, surfaces + j);
11243 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11245 R_BuildLightMap(ent, surfaces + j);
11246 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11248 // add to stats if desired
11249 if (r_speeds.integer && !skysurfaces && !depthonly)
11251 r_refdef.stats.entities_surfaces += numsurfacelist;
11252 for (j = 0;j < numsurfacelist;j++)
11253 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11256 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11259 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11261 static texture_t texture;
11262 static msurface_t surface;
11263 const msurface_t *surfacelist = &surface;
11265 // fake enough texture and surface state to render this geometry
11267 texture.update_lastrenderframe = -1; // regenerate this texture
11268 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11269 texture.currentskinframe = skinframe;
11270 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11271 texture.offsetmapping = OFFSETMAPPING_OFF;
11272 texture.offsetscale = 1;
11273 texture.specularscalemod = 1;
11274 texture.specularpowermod = 1;
11276 surface.texture = &texture;
11277 surface.num_triangles = numtriangles;
11278 surface.num_firsttriangle = firsttriangle;
11279 surface.num_vertices = numvertices;
11280 surface.num_firstvertex = firstvertex;
11283 rsurface.texture = R_GetCurrentTexture(surface.texture);
11284 rsurface.lightmaptexture = NULL;
11285 rsurface.deluxemaptexture = NULL;
11286 rsurface.uselightmaptexture = false;
11287 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11290 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)
11292 static msurface_t surface;
11293 const msurface_t *surfacelist = &surface;
11295 // fake enough texture and surface state to render this geometry
11296 surface.texture = texture;
11297 surface.num_triangles = numtriangles;
11298 surface.num_firsttriangle = firsttriangle;
11299 surface.num_vertices = numvertices;
11300 surface.num_firstvertex = firstvertex;
11303 rsurface.texture = R_GetCurrentTexture(surface.texture);
11304 rsurface.lightmaptexture = NULL;
11305 rsurface.deluxemaptexture = NULL;
11306 rsurface.uselightmaptexture = false;
11307 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);