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);
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);
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)
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 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3828 Cvar_SetValueQuick(&gl_combine, 1);
3829 Cvar_SetValueQuick(&r_glsl, 1);
3830 r_loadnormalmap = true;
3834 case RENDERPATH_GL13:
3835 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3836 Cvar_SetValueQuick(&gl_combine, 1);
3837 Cvar_SetValueQuick(&r_glsl, 0);
3838 r_loadnormalmap = false;
3839 r_loadgloss = false;
3842 case RENDERPATH_GL11:
3843 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844 Cvar_SetValueQuick(&gl_combine, 0);
3845 Cvar_SetValueQuick(&r_glsl, 0);
3846 r_loadnormalmap = false;
3847 r_loadgloss = false;
3850 case RENDERPATH_GLES2:
3851 Cvar_SetValueQuick(&r_textureunits, 1);
3852 Cvar_SetValueQuick(&gl_combine, 1);
3853 Cvar_SetValueQuick(&r_glsl, 1);
3854 r_loadnormalmap = true;
3855 r_loadgloss = false;
3861 R_FrameData_Reset();
3865 memset(r_queries, 0, sizeof(r_queries));
3867 r_qwskincache = NULL;
3868 r_qwskincache_size = 0;
3870 // due to caching of texture_t references, the collision cache must be reset
3871 Collision_Cache_Reset(true);
3873 // set up r_skinframe loading system for textures
3874 memset(&r_skinframe, 0, sizeof(r_skinframe));
3875 r_skinframe.loadsequence = 1;
3876 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3878 r_main_texturepool = R_AllocTexturePool();
3879 R_BuildBlankTextures();
3881 if (vid.support.arb_texture_cube_map)
3884 R_BuildNormalizationCube();
3886 r_texture_fogattenuation = NULL;
3887 r_texture_fogheighttexture = NULL;
3888 r_texture_gammaramps = NULL;
3889 //r_texture_fogintensity = NULL;
3890 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3891 memset(&r_waterstate, 0, sizeof(r_waterstate));
3892 r_glsl_permutation = NULL;
3893 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3894 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3895 glslshaderstring = NULL;
3897 r_hlsl_permutation = NULL;
3898 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3899 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3901 hlslshaderstring = NULL;
3902 memset(&r_svbsp, 0, sizeof (r_svbsp));
3904 r_refdef.fogmasktable_density = 0;
3907 void gl_main_shutdown(void)
3910 R_FrameData_Reset();
3912 R_Main_FreeViewCache();
3914 switch(vid.renderpath)
3916 case RENDERPATH_GL11:
3917 case RENDERPATH_GL13:
3918 case RENDERPATH_GL20:
3919 case RENDERPATH_GLES2:
3921 qglDeleteQueriesARB(r_maxqueries, r_queries);
3923 case RENDERPATH_D3D9:
3924 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3926 case RENDERPATH_D3D10:
3927 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3929 case RENDERPATH_D3D11:
3930 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3932 case RENDERPATH_SOFT:
3938 memset(r_queries, 0, sizeof(r_queries));
3940 r_qwskincache = NULL;
3941 r_qwskincache_size = 0;
3943 // clear out the r_skinframe state
3944 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3945 memset(&r_skinframe, 0, sizeof(r_skinframe));
3948 Mem_Free(r_svbsp.nodes);
3949 memset(&r_svbsp, 0, sizeof (r_svbsp));
3950 R_FreeTexturePool(&r_main_texturepool);
3951 loadingscreentexture = NULL;
3952 r_texture_blanknormalmap = NULL;
3953 r_texture_white = NULL;
3954 r_texture_grey128 = NULL;
3955 r_texture_black = NULL;
3956 r_texture_whitecube = NULL;
3957 r_texture_normalizationcube = NULL;
3958 r_texture_fogattenuation = NULL;
3959 r_texture_fogheighttexture = NULL;
3960 r_texture_gammaramps = NULL;
3961 r_texture_numcubemaps = 0;
3962 //r_texture_fogintensity = NULL;
3963 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3964 memset(&r_waterstate, 0, sizeof(r_waterstate));
3967 r_glsl_permutation = NULL;
3968 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3969 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3970 glslshaderstring = NULL;
3972 r_hlsl_permutation = NULL;
3973 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3974 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3976 hlslshaderstring = NULL;
3979 extern void CL_ParseEntityLump(char *entitystring);
3980 void gl_main_newmap(void)
3982 // FIXME: move this code to client
3983 char *entities, entname[MAX_QPATH];
3985 Mem_Free(r_qwskincache);
3986 r_qwskincache = NULL;
3987 r_qwskincache_size = 0;
3990 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3991 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3993 CL_ParseEntityLump(entities);
3997 if (cl.worldmodel->brush.entities)
3998 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4000 R_Main_FreeViewCache();
4002 R_FrameData_Reset();
4005 void GL_Main_Init(void)
4007 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4009 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4010 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4011 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4012 if (gamemode == GAME_NEHAHRA)
4014 Cvar_RegisterVariable (&gl_fogenable);
4015 Cvar_RegisterVariable (&gl_fogdensity);
4016 Cvar_RegisterVariable (&gl_fogred);
4017 Cvar_RegisterVariable (&gl_foggreen);
4018 Cvar_RegisterVariable (&gl_fogblue);
4019 Cvar_RegisterVariable (&gl_fogstart);
4020 Cvar_RegisterVariable (&gl_fogend);
4021 Cvar_RegisterVariable (&gl_skyclip);
4023 Cvar_RegisterVariable(&r_motionblur);
4024 Cvar_RegisterVariable(&r_motionblur_maxblur);
4025 Cvar_RegisterVariable(&r_motionblur_bmin);
4026 Cvar_RegisterVariable(&r_motionblur_vmin);
4027 Cvar_RegisterVariable(&r_motionblur_vmax);
4028 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4029 Cvar_RegisterVariable(&r_motionblur_randomize);
4030 Cvar_RegisterVariable(&r_damageblur);
4031 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4032 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4033 Cvar_RegisterVariable(&r_equalize_entities_by);
4034 Cvar_RegisterVariable(&r_equalize_entities_to);
4035 Cvar_RegisterVariable(&r_depthfirst);
4036 Cvar_RegisterVariable(&r_useinfinitefarclip);
4037 Cvar_RegisterVariable(&r_farclip_base);
4038 Cvar_RegisterVariable(&r_farclip_world);
4039 Cvar_RegisterVariable(&r_nearclip);
4040 Cvar_RegisterVariable(&r_showbboxes);
4041 Cvar_RegisterVariable(&r_showsurfaces);
4042 Cvar_RegisterVariable(&r_showtris);
4043 Cvar_RegisterVariable(&r_shownormals);
4044 Cvar_RegisterVariable(&r_showlighting);
4045 Cvar_RegisterVariable(&r_showshadowvolumes);
4046 Cvar_RegisterVariable(&r_showcollisionbrushes);
4047 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4048 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4049 Cvar_RegisterVariable(&r_showdisabledepthtest);
4050 Cvar_RegisterVariable(&r_drawportals);
4051 Cvar_RegisterVariable(&r_drawentities);
4052 Cvar_RegisterVariable(&r_draw2d);
4053 Cvar_RegisterVariable(&r_drawworld);
4054 Cvar_RegisterVariable(&r_cullentities_trace);
4055 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4056 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4057 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4058 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4059 Cvar_RegisterVariable(&r_drawviewmodel);
4060 Cvar_RegisterVariable(&r_drawexteriormodel);
4061 Cvar_RegisterVariable(&r_speeds);
4062 Cvar_RegisterVariable(&r_fullbrights);
4063 Cvar_RegisterVariable(&r_wateralpha);
4064 Cvar_RegisterVariable(&r_dynamic);
4065 Cvar_RegisterVariable(&r_fakelight);
4066 Cvar_RegisterVariable(&r_fakelight_intensity);
4067 Cvar_RegisterVariable(&r_fullbright);
4068 Cvar_RegisterVariable(&r_shadows);
4069 Cvar_RegisterVariable(&r_shadows_darken);
4070 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4071 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4072 Cvar_RegisterVariable(&r_shadows_throwdistance);
4073 Cvar_RegisterVariable(&r_shadows_throwdirection);
4074 Cvar_RegisterVariable(&r_shadows_focus);
4075 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4076 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4077 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4078 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4079 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4080 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4081 Cvar_RegisterVariable(&r_fog_exp2);
4082 Cvar_RegisterVariable(&r_fog_clear);
4083 Cvar_RegisterVariable(&r_drawfog);
4084 Cvar_RegisterVariable(&r_transparentdepthmasking);
4085 Cvar_RegisterVariable(&r_texture_dds_load);
4086 Cvar_RegisterVariable(&r_texture_dds_save);
4087 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4088 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4089 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4090 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4091 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4092 Cvar_RegisterVariable(&r_textureunits);
4093 Cvar_RegisterVariable(&gl_combine);
4094 Cvar_RegisterVariable(&r_glsl);
4095 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4096 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4097 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4098 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4099 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4100 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4101 Cvar_RegisterVariable(&r_glsl_postprocess);
4102 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4103 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4104 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4105 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4106 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4107 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4108 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4109 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4111 Cvar_RegisterVariable(&r_water);
4112 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4113 Cvar_RegisterVariable(&r_water_clippingplanebias);
4114 Cvar_RegisterVariable(&r_water_refractdistort);
4115 Cvar_RegisterVariable(&r_water_reflectdistort);
4116 Cvar_RegisterVariable(&r_water_scissormode);
4117 Cvar_RegisterVariable(&r_lerpsprites);
4118 Cvar_RegisterVariable(&r_lerpmodels);
4119 Cvar_RegisterVariable(&r_lerplightstyles);
4120 Cvar_RegisterVariable(&r_waterscroll);
4121 Cvar_RegisterVariable(&r_bloom);
4122 Cvar_RegisterVariable(&r_bloom_colorscale);
4123 Cvar_RegisterVariable(&r_bloom_brighten);
4124 Cvar_RegisterVariable(&r_bloom_blur);
4125 Cvar_RegisterVariable(&r_bloom_resolution);
4126 Cvar_RegisterVariable(&r_bloom_colorexponent);
4127 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4128 Cvar_RegisterVariable(&r_hdr);
4129 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4130 Cvar_RegisterVariable(&r_hdr_glowintensity);
4131 Cvar_RegisterVariable(&r_hdr_range);
4132 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4133 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4134 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4135 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4136 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4137 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4138 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4139 Cvar_RegisterVariable(&developer_texturelogging);
4140 Cvar_RegisterVariable(&gl_lightmaps);
4141 Cvar_RegisterVariable(&r_test);
4142 Cvar_RegisterVariable(&r_glsl_saturation);
4143 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4144 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4145 Cvar_RegisterVariable(&r_framedatasize);
4146 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4147 Cvar_SetValue("r_fullbrights", 0);
4148 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4150 Cvar_RegisterVariable(&r_track_sprites);
4151 Cvar_RegisterVariable(&r_track_sprites_flags);
4152 Cvar_RegisterVariable(&r_track_sprites_scalew);
4153 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4154 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4155 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4156 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4157 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4160 extern void R_Textures_Init(void);
4161 extern void GL_Draw_Init(void);
4162 extern void GL_Main_Init(void);
4163 extern void R_Shadow_Init(void);
4164 extern void R_Sky_Init(void);
4165 extern void GL_Surf_Init(void);
4166 extern void R_Particles_Init(void);
4167 extern void R_Explosion_Init(void);
4168 extern void gl_backend_init(void);
4169 extern void Sbar_Init(void);
4170 extern void R_LightningBeams_Init(void);
4171 extern void Mod_RenderInit(void);
4172 extern void Font_Init(void);
4174 void Render_Init(void)
4187 R_LightningBeams_Init();
4196 extern char *ENGINE_EXTENSIONS;
4199 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4200 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4201 gl_version = (const char *)qglGetString(GL_VERSION);
4202 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4206 if (!gl_platformextensions)
4207 gl_platformextensions = "";
4209 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4210 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4211 Con_Printf("GL_VERSION: %s\n", gl_version);
4212 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4213 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4215 VID_CheckExtensions();
4217 // LordHavoc: report supported extensions
4218 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4220 // clear to black (loading plaque will be seen over this)
4221 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4224 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4228 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4230 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4233 p = r_refdef.view.frustum + i;
4238 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4242 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4246 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4250 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4254 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4258 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4262 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4266 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4274 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4278 for (i = 0;i < numplanes;i++)
4285 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4289 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4293 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4297 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4301 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4305 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4309 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4313 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4321 //==================================================================================
4323 // LordHavoc: this stores temporary data used within the same frame
4325 typedef struct r_framedata_mem_s
4327 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4328 size_t size; // how much usable space
4329 size_t current; // how much space in use
4330 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4331 size_t wantedsize; // how much space was allocated
4332 unsigned char *data; // start of real data (16byte aligned)
4336 static r_framedata_mem_t *r_framedata_mem;
4338 void R_FrameData_Reset(void)
4340 while (r_framedata_mem)
4342 r_framedata_mem_t *next = r_framedata_mem->purge;
4343 Mem_Free(r_framedata_mem);
4344 r_framedata_mem = next;
4348 void R_FrameData_Resize(void)
4351 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4352 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4353 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4355 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4356 newmem->wantedsize = wantedsize;
4357 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4358 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4359 newmem->current = 0;
4361 newmem->purge = r_framedata_mem;
4362 r_framedata_mem = newmem;
4366 void R_FrameData_NewFrame(void)
4368 R_FrameData_Resize();
4369 if (!r_framedata_mem)
4371 // if we ran out of space on the last frame, free the old memory now
4372 while (r_framedata_mem->purge)
4374 // repeatedly remove the second item in the list, leaving only head
4375 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4376 Mem_Free(r_framedata_mem->purge);
4377 r_framedata_mem->purge = next;
4379 // reset the current mem pointer
4380 r_framedata_mem->current = 0;
4381 r_framedata_mem->mark = 0;
4384 void *R_FrameData_Alloc(size_t size)
4388 // align to 16 byte boundary - the data pointer is already aligned, so we
4389 // only need to ensure the size of every allocation is also aligned
4390 size = (size + 15) & ~15;
4392 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4394 // emergency - we ran out of space, allocate more memory
4395 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4396 R_FrameData_Resize();
4399 data = r_framedata_mem->data + r_framedata_mem->current;
4400 r_framedata_mem->current += size;
4402 // count the usage for stats
4403 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4404 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4406 return (void *)data;
4409 void *R_FrameData_Store(size_t size, void *data)
4411 void *d = R_FrameData_Alloc(size);
4413 memcpy(d, data, size);
4417 void R_FrameData_SetMark(void)
4419 if (!r_framedata_mem)
4421 r_framedata_mem->mark = r_framedata_mem->current;
4424 void R_FrameData_ReturnToMark(void)
4426 if (!r_framedata_mem)
4428 r_framedata_mem->current = r_framedata_mem->mark;
4431 //==================================================================================
4433 // LordHavoc: animcache originally written by Echon, rewritten since then
4436 * Animation cache prevents re-generating mesh data for an animated model
4437 * multiple times in one frame for lighting, shadowing, reflections, etc.
4440 void R_AnimCache_Free(void)
4444 void R_AnimCache_ClearCache(void)
4447 entity_render_t *ent;
4449 for (i = 0;i < r_refdef.scene.numentities;i++)
4451 ent = r_refdef.scene.entities[i];
4452 ent->animcache_vertex3f = NULL;
4453 ent->animcache_normal3f = NULL;
4454 ent->animcache_svector3f = NULL;
4455 ent->animcache_tvector3f = NULL;
4456 ent->animcache_vertexmesh = NULL;
4457 ent->animcache_vertex3fbuffer = NULL;
4458 ent->animcache_vertexmeshbuffer = NULL;
4462 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4466 // check if we need the meshbuffers
4467 if (!vid.useinterleavedarrays)
4470 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4471 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4472 // TODO: upload vertex3f buffer?
4473 if (ent->animcache_vertexmesh)
4475 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4476 for (i = 0;i < numvertices;i++)
4477 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4478 if (ent->animcache_svector3f)
4479 for (i = 0;i < numvertices;i++)
4480 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4481 if (ent->animcache_tvector3f)
4482 for (i = 0;i < numvertices;i++)
4483 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4484 if (ent->animcache_normal3f)
4485 for (i = 0;i < numvertices;i++)
4486 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4487 // TODO: upload vertexmeshbuffer?
4491 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4493 dp_model_t *model = ent->model;
4495 // see if it's already cached this frame
4496 if (ent->animcache_vertex3f)
4498 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4499 if (wantnormals || wanttangents)
4501 if (ent->animcache_normal3f)
4502 wantnormals = false;
4503 if (ent->animcache_svector3f)
4504 wanttangents = false;
4505 if (wantnormals || wanttangents)
4507 numvertices = model->surfmesh.num_vertices;
4509 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4512 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4513 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4515 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4516 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4522 // see if this ent is worth caching
4523 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4525 // get some memory for this entity and generate mesh data
4526 numvertices = model->surfmesh.num_vertices;
4527 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4529 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4535 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4536 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4541 void R_AnimCache_CacheVisibleEntities(void)
4544 qboolean wantnormals = true;
4545 qboolean wanttangents = !r_showsurfaces.integer;
4547 switch(vid.renderpath)
4549 case RENDERPATH_GL20:
4550 case RENDERPATH_D3D9:
4551 case RENDERPATH_D3D10:
4552 case RENDERPATH_D3D11:
4553 case RENDERPATH_GLES2:
4555 case RENDERPATH_GL13:
4556 case RENDERPATH_GL11:
4557 wanttangents = false;
4559 case RENDERPATH_SOFT:
4563 if (r_shownormals.integer)
4564 wanttangents = wantnormals = true;
4566 // TODO: thread this
4567 // NOTE: R_PrepareRTLights() also caches entities
4569 for (i = 0;i < r_refdef.scene.numentities;i++)
4570 if (r_refdef.viewcache.entityvisible[i])
4571 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4574 //==================================================================================
4576 static void R_View_UpdateEntityLighting (void)
4579 entity_render_t *ent;
4580 vec3_t tempdiffusenormal, avg;
4581 vec_t f, fa, fd, fdd;
4582 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4584 for (i = 0;i < r_refdef.scene.numentities;i++)
4586 ent = r_refdef.scene.entities[i];
4588 // skip unseen models
4589 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4593 if (ent->model && ent->model->brush.num_leafs)
4595 // TODO: use modellight for r_ambient settings on world?
4596 VectorSet(ent->modellight_ambient, 0, 0, 0);
4597 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4598 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4602 // fetch the lighting from the worldmodel data
4603 VectorClear(ent->modellight_ambient);
4604 VectorClear(ent->modellight_diffuse);
4605 VectorClear(tempdiffusenormal);
4606 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4609 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4611 // complete lightning for lit sprites
4612 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4613 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4615 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4616 org[2] = org[2] + r_overheadsprites_pushback.value;
4617 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4620 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4622 if(ent->flags & RENDER_EQUALIZE)
4624 // first fix up ambient lighting...
4625 if(r_equalize_entities_minambient.value > 0)
4627 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4630 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4631 if(fa < r_equalize_entities_minambient.value * fd)
4634 // fa'/fd' = minambient
4635 // fa'+0.25*fd' = fa+0.25*fd
4637 // fa' = fd' * minambient
4638 // fd'*(0.25+minambient) = fa+0.25*fd
4640 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4641 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4643 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4644 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
4645 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4646 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4651 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4653 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4654 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4658 // adjust brightness and saturation to target
4659 avg[0] = avg[1] = avg[2] = fa / f;
4660 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4661 avg[0] = avg[1] = avg[2] = fd / f;
4662 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4668 VectorSet(ent->modellight_ambient, 1, 1, 1);
4670 // move the light direction into modelspace coordinates for lighting code
4671 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4672 if(VectorLength2(ent->modellight_lightdir) == 0)
4673 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4674 VectorNormalize(ent->modellight_lightdir);
4678 #define MAX_LINEOFSIGHTTRACES 64
4680 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4683 vec3_t boxmins, boxmaxs;
4686 dp_model_t *model = r_refdef.scene.worldmodel;
4688 if (!model || !model->brush.TraceLineOfSight)
4691 // expand the box a little
4692 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4693 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4694 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4695 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4696 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4697 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4699 // return true if eye is inside enlarged box
4700 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4704 VectorCopy(eye, start);
4705 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4706 if (model->brush.TraceLineOfSight(model, start, end))
4709 // try various random positions
4710 for (i = 0;i < numsamples;i++)
4712 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4713 if (model->brush.TraceLineOfSight(model, start, end))
4721 static void R_View_UpdateEntityVisible (void)
4726 entity_render_t *ent;
4728 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4729 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4730 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4731 : RENDER_EXTERIORMODEL;
4732 if (!r_drawviewmodel.integer)
4733 renderimask |= RENDER_VIEWMODEL;
4734 if (!r_drawexteriormodel.integer)
4735 renderimask |= RENDER_EXTERIORMODEL;
4736 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4738 // worldmodel can check visibility
4739 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4740 for (i = 0;i < r_refdef.scene.numentities;i++)
4742 ent = r_refdef.scene.entities[i];
4743 if (!(ent->flags & renderimask))
4744 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)))
4745 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))
4746 r_refdef.viewcache.entityvisible[i] = true;
4748 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4749 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4751 for (i = 0;i < r_refdef.scene.numentities;i++)
4753 ent = r_refdef.scene.entities[i];
4754 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4756 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4758 continue; // temp entities do pvs only
4759 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4760 ent->last_trace_visibility = realtime;
4761 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4762 r_refdef.viewcache.entityvisible[i] = 0;
4769 // no worldmodel or it can't check visibility
4770 for (i = 0;i < r_refdef.scene.numentities;i++)
4772 ent = r_refdef.scene.entities[i];
4773 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));
4778 /// only used if skyrendermasked, and normally returns false
4779 int R_DrawBrushModelsSky (void)
4782 entity_render_t *ent;
4785 for (i = 0;i < r_refdef.scene.numentities;i++)
4787 if (!r_refdef.viewcache.entityvisible[i])
4789 ent = r_refdef.scene.entities[i];
4790 if (!ent->model || !ent->model->DrawSky)
4792 ent->model->DrawSky(ent);
4798 static void R_DrawNoModel(entity_render_t *ent);
4799 static void R_DrawModels(void)
4802 entity_render_t *ent;
4804 for (i = 0;i < r_refdef.scene.numentities;i++)
4806 if (!r_refdef.viewcache.entityvisible[i])
4808 ent = r_refdef.scene.entities[i];
4809 r_refdef.stats.entities++;
4810 if (ent->model && ent->model->Draw != NULL)
4811 ent->model->Draw(ent);
4817 static void R_DrawModelsDepth(void)
4820 entity_render_t *ent;
4822 for (i = 0;i < r_refdef.scene.numentities;i++)
4824 if (!r_refdef.viewcache.entityvisible[i])
4826 ent = r_refdef.scene.entities[i];
4827 if (ent->model && ent->model->DrawDepth != NULL)
4828 ent->model->DrawDepth(ent);
4832 static void R_DrawModelsDebug(void)
4835 entity_render_t *ent;
4837 for (i = 0;i < r_refdef.scene.numentities;i++)
4839 if (!r_refdef.viewcache.entityvisible[i])
4841 ent = r_refdef.scene.entities[i];
4842 if (ent->model && ent->model->DrawDebug != NULL)
4843 ent->model->DrawDebug(ent);
4847 static void R_DrawModelsAddWaterPlanes(void)
4850 entity_render_t *ent;
4852 for (i = 0;i < r_refdef.scene.numentities;i++)
4854 if (!r_refdef.viewcache.entityvisible[i])
4856 ent = r_refdef.scene.entities[i];
4857 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4858 ent->model->DrawAddWaterPlanes(ent);
4862 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4864 if (r_hdr_irisadaptation.integer)
4868 vec3_t diffusenormal;
4873 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4874 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4875 brightness = max(0.0000001f, brightness);
4876 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4877 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4878 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4879 current = r_hdr_irisadaptation_value.value;
4881 current = min(current + adjust, goal);
4882 else if (current > goal)
4883 current = max(current - adjust, goal);
4884 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4885 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4887 else if (r_hdr_irisadaptation_value.value != 1.0f)
4888 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4891 static void R_View_SetFrustum(const int *scissor)
4894 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4895 vec3_t forward, left, up, origin, v;
4899 // flipped x coordinates (because x points left here)
4900 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4901 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4903 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4904 switch(vid.renderpath)
4906 case RENDERPATH_D3D9:
4907 case RENDERPATH_D3D10:
4908 case RENDERPATH_D3D11:
4909 case RENDERPATH_SOFT:
4910 // non-flipped y coordinates
4911 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4912 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4914 case RENDERPATH_GL11:
4915 case RENDERPATH_GL13:
4916 case RENDERPATH_GL20:
4917 case RENDERPATH_GLES2:
4918 // non-flipped y coordinates
4919 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4920 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4925 // we can't trust r_refdef.view.forward and friends in reflected scenes
4926 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4929 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4930 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4931 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4932 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4933 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4934 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4935 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4936 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4937 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4938 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4939 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4940 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4944 zNear = r_refdef.nearclip;
4945 nudge = 1.0 - 1.0 / (1<<23);
4946 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4947 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4948 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4949 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4950 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4951 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4952 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4953 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4959 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4960 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4961 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4962 r_refdef.view.frustum[0].dist = m[15] - m[12];
4964 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4965 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4966 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4967 r_refdef.view.frustum[1].dist = m[15] + m[12];
4969 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4970 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4971 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4972 r_refdef.view.frustum[2].dist = m[15] - m[13];
4974 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4975 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4976 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4977 r_refdef.view.frustum[3].dist = m[15] + m[13];
4979 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4980 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4981 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4982 r_refdef.view.frustum[4].dist = m[15] - m[14];
4984 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4985 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4986 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4987 r_refdef.view.frustum[5].dist = m[15] + m[14];
4990 if (r_refdef.view.useperspective)
4992 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4993 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]);
4994 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]);
4995 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]);
4996 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]);
4998 // then the normals from the corners relative to origin
4999 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5000 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5001 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5002 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5004 // in a NORMAL view, forward cross left == up
5005 // in a REFLECTED view, forward cross left == down
5006 // so our cross products above need to be adjusted for a left handed coordinate system
5007 CrossProduct(forward, left, v);
5008 if(DotProduct(v, up) < 0)
5010 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5011 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5012 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5013 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5016 // Leaving those out was a mistake, those were in the old code, and they
5017 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5018 // I couldn't reproduce it after adding those normalizations. --blub
5019 VectorNormalize(r_refdef.view.frustum[0].normal);
5020 VectorNormalize(r_refdef.view.frustum[1].normal);
5021 VectorNormalize(r_refdef.view.frustum[2].normal);
5022 VectorNormalize(r_refdef.view.frustum[3].normal);
5024 // make the corners absolute
5025 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5026 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5027 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5028 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5031 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5033 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5034 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5035 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5036 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5037 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5041 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5042 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5043 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5044 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5045 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5046 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5047 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5048 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5049 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5050 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5052 r_refdef.view.numfrustumplanes = 5;
5054 if (r_refdef.view.useclipplane)
5056 r_refdef.view.numfrustumplanes = 6;
5057 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5060 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5061 PlaneClassify(r_refdef.view.frustum + i);
5063 // LordHavoc: note to all quake engine coders, Quake had a special case
5064 // for 90 degrees which assumed a square view (wrong), so I removed it,
5065 // Quake2 has it disabled as well.
5067 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5068 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5069 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5070 //PlaneClassify(&frustum[0]);
5072 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5073 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5074 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5075 //PlaneClassify(&frustum[1]);
5077 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5078 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5079 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5080 //PlaneClassify(&frustum[2]);
5082 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5083 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5084 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5085 //PlaneClassify(&frustum[3]);
5088 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5089 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5090 //PlaneClassify(&frustum[4]);
5093 void R_View_UpdateWithScissor(const int *myscissor)
5095 R_Main_ResizeViewCache();
5096 R_View_SetFrustum(myscissor);
5097 R_View_WorldVisibility(r_refdef.view.useclipplane);
5098 R_View_UpdateEntityVisible();
5099 R_View_UpdateEntityLighting();
5102 void R_View_Update(void)
5104 R_Main_ResizeViewCache();
5105 R_View_SetFrustum(NULL);
5106 R_View_WorldVisibility(r_refdef.view.useclipplane);
5107 R_View_UpdateEntityVisible();
5108 R_View_UpdateEntityLighting();
5111 void R_SetupView(qboolean allowwaterclippingplane)
5113 const float *customclipplane = NULL;
5115 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5117 // LordHavoc: couldn't figure out how to make this approach the
5118 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5119 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5120 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5121 dist = r_refdef.view.clipplane.dist;
5122 plane[0] = r_refdef.view.clipplane.normal[0];
5123 plane[1] = r_refdef.view.clipplane.normal[1];
5124 plane[2] = r_refdef.view.clipplane.normal[2];
5126 customclipplane = plane;
5129 if (!r_refdef.view.useperspective)
5130 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);
5131 else if (vid.stencil && r_useinfinitefarclip.integer)
5132 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);
5134 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);
5135 R_SetViewport(&r_refdef.view.viewport);
5138 void R_EntityMatrix(const matrix4x4_t *matrix)
5140 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5142 gl_modelmatrixchanged = false;
5143 gl_modelmatrix = *matrix;
5144 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5145 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5146 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5147 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5149 switch(vid.renderpath)
5151 case RENDERPATH_D3D9:
5153 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5154 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5157 case RENDERPATH_D3D10:
5158 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5160 case RENDERPATH_D3D11:
5161 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5163 case RENDERPATH_GL13:
5164 case RENDERPATH_GL11:
5165 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5167 case RENDERPATH_SOFT:
5168 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5169 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5171 case RENDERPATH_GL20:
5172 case RENDERPATH_GLES2:
5173 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5174 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5180 void R_ResetViewRendering2D(void)
5182 r_viewport_t viewport;
5185 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5186 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);
5187 R_SetViewport(&viewport);
5188 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5189 GL_Color(1, 1, 1, 1);
5190 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5191 GL_BlendFunc(GL_ONE, GL_ZERO);
5192 GL_ScissorTest(false);
5193 GL_DepthMask(false);
5194 GL_DepthRange(0, 1);
5195 GL_DepthTest(false);
5196 GL_DepthFunc(GL_LEQUAL);
5197 R_EntityMatrix(&identitymatrix);
5198 R_Mesh_ResetTextureState();
5199 GL_PolygonOffset(0, 0);
5200 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5201 switch(vid.renderpath)
5203 case RENDERPATH_GL11:
5204 case RENDERPATH_GL13:
5205 case RENDERPATH_GL20:
5206 case RENDERPATH_GLES2:
5207 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5209 case RENDERPATH_D3D9:
5210 case RENDERPATH_D3D10:
5211 case RENDERPATH_D3D11:
5212 case RENDERPATH_SOFT:
5215 GL_CullFace(GL_NONE);
5218 void R_ResetViewRendering3D(void)
5223 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5224 GL_Color(1, 1, 1, 1);
5225 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5226 GL_BlendFunc(GL_ONE, GL_ZERO);
5227 GL_ScissorTest(true);
5229 GL_DepthRange(0, 1);
5231 GL_DepthFunc(GL_LEQUAL);
5232 R_EntityMatrix(&identitymatrix);
5233 R_Mesh_ResetTextureState();
5234 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5235 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5236 switch(vid.renderpath)
5238 case RENDERPATH_GL11:
5239 case RENDERPATH_GL13:
5240 case RENDERPATH_GL20:
5241 case RENDERPATH_GLES2:
5242 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5244 case RENDERPATH_D3D9:
5245 case RENDERPATH_D3D10:
5246 case RENDERPATH_D3D11:
5247 case RENDERPATH_SOFT:
5250 GL_CullFace(r_refdef.view.cullface_back);
5255 R_RenderView_UpdateViewVectors
5258 static void R_RenderView_UpdateViewVectors(void)
5260 // break apart the view matrix into vectors for various purposes
5261 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5262 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5263 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5264 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5265 // make an inverted copy of the view matrix for tracking sprites
5266 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5269 void R_RenderScene(void);
5270 void R_RenderWaterPlanes(void);
5272 static void R_Water_StartFrame(void)
5275 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5276 r_waterstate_waterplane_t *p;
5278 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5281 switch(vid.renderpath)
5283 case RENDERPATH_GL20:
5284 case RENDERPATH_D3D9:
5285 case RENDERPATH_D3D10:
5286 case RENDERPATH_D3D11:
5287 case RENDERPATH_SOFT:
5288 case RENDERPATH_GLES2:
5290 case RENDERPATH_GL13:
5291 case RENDERPATH_GL11:
5295 // set waterwidth and waterheight to the water resolution that will be
5296 // used (often less than the screen resolution for faster rendering)
5297 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5298 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5300 // calculate desired texture sizes
5301 // can't use water if the card does not support the texture size
5302 if (!r_water.integer || r_showsurfaces.integer)
5303 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5304 else if (vid.support.arb_texture_non_power_of_two)
5306 texturewidth = waterwidth;
5307 textureheight = waterheight;
5308 camerawidth = waterwidth;
5309 cameraheight = waterheight;
5313 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5314 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5315 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5316 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5319 // allocate textures as needed
5320 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5322 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5323 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5325 if (p->texture_refraction)
5326 R_FreeTexture(p->texture_refraction);
5327 p->texture_refraction = NULL;
5328 if (p->texture_reflection)
5329 R_FreeTexture(p->texture_reflection);
5330 p->texture_reflection = NULL;
5331 if (p->texture_camera)
5332 R_FreeTexture(p->texture_camera);
5333 p->texture_camera = NULL;
5335 memset(&r_waterstate, 0, sizeof(r_waterstate));
5336 r_waterstate.texturewidth = texturewidth;
5337 r_waterstate.textureheight = textureheight;
5338 r_waterstate.camerawidth = camerawidth;
5339 r_waterstate.cameraheight = cameraheight;
5342 if (r_waterstate.texturewidth)
5344 r_waterstate.enabled = true;
5346 // when doing a reduced render (HDR) we want to use a smaller area
5347 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5348 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5350 // set up variables that will be used in shader setup
5351 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5352 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5353 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5354 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5357 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5358 r_waterstate.numwaterplanes = 0;
5361 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5363 int triangleindex, planeindex;
5369 r_waterstate_waterplane_t *p;
5370 texture_t *t = R_GetCurrentTexture(surface->texture);
5372 // just use the first triangle with a valid normal for any decisions
5373 VectorClear(normal);
5374 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5376 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5377 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5378 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5379 TriangleNormal(vert[0], vert[1], vert[2], normal);
5380 if (VectorLength2(normal) >= 0.001)
5384 VectorCopy(normal, plane.normal);
5385 VectorNormalize(plane.normal);
5386 plane.dist = DotProduct(vert[0], plane.normal);
5387 PlaneClassify(&plane);
5388 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5390 // skip backfaces (except if nocullface is set)
5391 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5393 VectorNegate(plane.normal, plane.normal);
5395 PlaneClassify(&plane);
5399 // find a matching plane if there is one
5400 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5401 if(p->camera_entity == t->camera_entity)
5402 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5404 if (planeindex >= r_waterstate.maxwaterplanes)
5405 return; // nothing we can do, out of planes
5407 // if this triangle does not fit any known plane rendered this frame, add one
5408 if (planeindex >= r_waterstate.numwaterplanes)
5410 // store the new plane
5411 r_waterstate.numwaterplanes++;
5413 // clear materialflags and pvs
5414 p->materialflags = 0;
5415 p->pvsvalid = false;
5416 p->camera_entity = t->camera_entity;
5417 VectorCopy(surface->mins, p->mins);
5418 VectorCopy(surface->maxs, p->maxs);
5423 p->mins[0] = min(p->mins[0], surface->mins[0]);
5424 p->mins[1] = min(p->mins[1], surface->mins[1]);
5425 p->mins[2] = min(p->mins[2], surface->mins[2]);
5426 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5427 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5428 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5430 // merge this surface's materialflags into the waterplane
5431 p->materialflags |= t->currentmaterialflags;
5432 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5434 // merge this surface's PVS into the waterplane
5435 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5436 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5437 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5439 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5445 static void R_Water_ProcessPlanes(void)
5448 r_refdef_view_t originalview;
5449 r_refdef_view_t myview;
5451 r_waterstate_waterplane_t *p;
5454 originalview = r_refdef.view;
5456 // make sure enough textures are allocated
5457 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5459 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5461 if (!p->texture_refraction)
5462 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);
5463 if (!p->texture_refraction)
5466 else if (p->materialflags & MATERIALFLAG_CAMERA)
5468 if (!p->texture_camera)
5469 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);
5470 if (!p->texture_camera)
5474 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5476 if (!p->texture_reflection)
5477 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);
5478 if (!p->texture_reflection)
5484 r_refdef.view = originalview;
5485 r_refdef.view.showdebug = false;
5486 r_refdef.view.width = r_waterstate.waterwidth;
5487 r_refdef.view.height = r_waterstate.waterheight;
5488 r_refdef.view.useclipplane = true;
5489 myview = r_refdef.view;
5490 r_waterstate.renderingscene = true;
5491 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5493 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5495 r_refdef.view = myview;
5496 if(r_water_scissormode.integer)
5499 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5500 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5503 // render reflected scene and copy into texture
5504 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5505 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5506 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5507 r_refdef.view.clipplane = p->plane;
5509 // reverse the cullface settings for this render
5510 r_refdef.view.cullface_front = GL_FRONT;
5511 r_refdef.view.cullface_back = GL_BACK;
5512 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5514 r_refdef.view.usecustompvs = true;
5516 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5518 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5521 R_ResetViewRendering3D();
5522 R_ClearScreen(r_refdef.fogenabled);
5523 if(r_water_scissormode.integer & 2)
5524 R_View_UpdateWithScissor(myscissor);
5527 if(r_water_scissormode.integer & 1)
5528 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5531 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);
5534 // render the normal view scene and copy into texture
5535 // (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)
5536 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5538 r_refdef.view = myview;
5539 if(r_water_scissormode.integer)
5542 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5543 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5546 r_waterstate.renderingrefraction = true;
5548 r_refdef.view.clipplane = p->plane;
5549 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5550 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5552 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5554 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5555 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5556 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5557 R_RenderView_UpdateViewVectors();
5558 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5560 r_refdef.view.usecustompvs = true;
5561 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);
5565 PlaneClassify(&r_refdef.view.clipplane);
5567 R_ResetViewRendering3D();
5568 R_ClearScreen(r_refdef.fogenabled);
5569 if(r_water_scissormode.integer & 2)
5570 R_View_UpdateWithScissor(myscissor);
5573 if(r_water_scissormode.integer & 1)
5574 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5577 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);
5578 r_waterstate.renderingrefraction = false;
5580 else if (p->materialflags & MATERIALFLAG_CAMERA)
5582 r_refdef.view = myview;
5584 r_refdef.view.clipplane = p->plane;
5585 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5586 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5588 r_refdef.view.width = r_waterstate.camerawidth;
5589 r_refdef.view.height = r_waterstate.cameraheight;
5590 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5591 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5593 if(p->camera_entity)
5595 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5596 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5599 // note: all of the view is used for displaying... so
5600 // there is no use in scissoring
5602 // reverse the cullface settings for this render
5603 r_refdef.view.cullface_front = GL_FRONT;
5604 r_refdef.view.cullface_back = GL_BACK;
5605 // also reverse the view matrix
5606 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
5607 R_RenderView_UpdateViewVectors();
5608 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5610 r_refdef.view.usecustompvs = true;
5611 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);
5614 // camera needs no clipplane
5615 r_refdef.view.useclipplane = false;
5617 PlaneClassify(&r_refdef.view.clipplane);
5619 R_ResetViewRendering3D();
5620 R_ClearScreen(r_refdef.fogenabled);
5624 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);
5625 r_waterstate.renderingrefraction = false;
5629 r_waterstate.renderingscene = false;
5630 r_refdef.view = originalview;
5631 R_ResetViewRendering3D();
5632 R_ClearScreen(r_refdef.fogenabled);
5636 r_refdef.view = originalview;
5637 r_waterstate.renderingscene = false;
5638 Cvar_SetValueQuick(&r_water, 0);
5639 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5643 void R_Bloom_StartFrame(void)
5645 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5647 switch(vid.renderpath)
5649 case RENDERPATH_GL20:
5650 case RENDERPATH_D3D9:
5651 case RENDERPATH_D3D10:
5652 case RENDERPATH_D3D11:
5653 case RENDERPATH_SOFT:
5654 case RENDERPATH_GLES2:
5656 case RENDERPATH_GL13:
5657 case RENDERPATH_GL11:
5661 // set bloomwidth and bloomheight to the bloom resolution that will be
5662 // used (often less than the screen resolution for faster rendering)
5663 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5664 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5665 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5666 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5667 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5669 // calculate desired texture sizes
5670 if (vid.support.arb_texture_non_power_of_two)
5672 screentexturewidth = r_refdef.view.width;
5673 screentextureheight = r_refdef.view.height;
5674 bloomtexturewidth = r_bloomstate.bloomwidth;
5675 bloomtextureheight = r_bloomstate.bloomheight;
5679 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5680 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5681 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5682 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5685 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))
5687 Cvar_SetValueQuick(&r_hdr, 0);
5688 Cvar_SetValueQuick(&r_bloom, 0);
5689 Cvar_SetValueQuick(&r_motionblur, 0);
5690 Cvar_SetValueQuick(&r_damageblur, 0);
5693 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)))
5694 screentexturewidth = screentextureheight = 0;
5695 if (!r_hdr.integer && !r_bloom.integer)
5696 bloomtexturewidth = bloomtextureheight = 0;
5698 // allocate textures as needed
5699 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5701 if (r_bloomstate.texture_screen)
5702 R_FreeTexture(r_bloomstate.texture_screen);
5703 r_bloomstate.texture_screen = NULL;
5704 r_bloomstate.screentexturewidth = screentexturewidth;
5705 r_bloomstate.screentextureheight = screentextureheight;
5706 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5707 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);
5709 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5711 if (r_bloomstate.texture_bloom)
5712 R_FreeTexture(r_bloomstate.texture_bloom);
5713 r_bloomstate.texture_bloom = NULL;
5714 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5715 r_bloomstate.bloomtextureheight = bloomtextureheight;
5716 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5717 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);
5720 // when doing a reduced render (HDR) we want to use a smaller area
5721 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5722 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5723 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5724 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5725 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5727 // set up a texcoord array for the full resolution screen image
5728 // (we have to keep this around to copy back during final render)
5729 r_bloomstate.screentexcoord2f[0] = 0;
5730 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5731 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5732 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5733 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5734 r_bloomstate.screentexcoord2f[5] = 0;
5735 r_bloomstate.screentexcoord2f[6] = 0;
5736 r_bloomstate.screentexcoord2f[7] = 0;
5738 // set up a texcoord array for the reduced resolution bloom image
5739 // (which will be additive blended over the screen image)
5740 r_bloomstate.bloomtexcoord2f[0] = 0;
5741 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5742 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5743 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5744 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5745 r_bloomstate.bloomtexcoord2f[5] = 0;
5746 r_bloomstate.bloomtexcoord2f[6] = 0;
5747 r_bloomstate.bloomtexcoord2f[7] = 0;
5749 switch(vid.renderpath)
5751 case RENDERPATH_GL11:
5752 case RENDERPATH_GL13:
5753 case RENDERPATH_GL20:
5754 case RENDERPATH_SOFT:
5755 case RENDERPATH_GLES2:
5757 case RENDERPATH_D3D9:
5758 case RENDERPATH_D3D10:
5759 case RENDERPATH_D3D11:
5762 for (i = 0;i < 4;i++)
5764 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5765 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5766 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5767 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5773 if (r_hdr.integer || r_bloom.integer)
5775 r_bloomstate.enabled = true;
5776 r_bloomstate.hdr = r_hdr.integer != 0;
5779 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);
5782 void R_Bloom_CopyBloomTexture(float colorscale)
5784 r_refdef.stats.bloom++;
5786 // scale down screen texture to the bloom texture size
5788 R_SetViewport(&r_bloomstate.viewport);
5789 GL_BlendFunc(GL_ONE, GL_ZERO);
5790 GL_Color(colorscale, colorscale, colorscale, 1);
5791 // 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...
5792 switch(vid.renderpath)
5794 case RENDERPATH_GL11:
5795 case RENDERPATH_GL13:
5796 case RENDERPATH_GL20:
5797 case RENDERPATH_SOFT:
5798 case RENDERPATH_GLES2:
5799 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5801 case RENDERPATH_D3D9:
5802 case RENDERPATH_D3D10:
5803 case RENDERPATH_D3D11:
5804 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5807 // TODO: do boxfilter scale-down in shader?
5808 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5809 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5810 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5812 // we now have a bloom image in the framebuffer
5813 // copy it into the bloom image texture for later processing
5814 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);
5815 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5818 void R_Bloom_CopyHDRTexture(void)
5820 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);
5821 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5824 void R_Bloom_MakeTexture(void)
5827 float xoffset, yoffset, r, brighten;
5829 r_refdef.stats.bloom++;
5831 R_ResetViewRendering2D();
5833 // we have a bloom image in the framebuffer
5835 R_SetViewport(&r_bloomstate.viewport);
5837 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5840 r = bound(0, r_bloom_colorexponent.value / x, 1);
5841 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5843 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5844 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5845 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5846 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5848 // copy the vertically blurred bloom view to a texture
5849 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);
5850 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5853 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5854 brighten = r_bloom_brighten.value;
5856 brighten *= r_hdr_range.value;
5857 brighten = sqrt(brighten);
5859 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5860 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5862 for (dir = 0;dir < 2;dir++)
5864 // blend on at multiple vertical offsets to achieve a vertical blur
5865 // TODO: do offset blends using GLSL
5866 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5867 GL_BlendFunc(GL_ONE, GL_ZERO);
5868 for (x = -range;x <= range;x++)
5870 if (!dir){xoffset = 0;yoffset = x;}
5871 else {xoffset = x;yoffset = 0;}
5872 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5873 yoffset /= (float)r_bloomstate.bloomtextureheight;
5874 // compute a texcoord array with the specified x and y offset
5875 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5876 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5877 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5878 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5879 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5880 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5881 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5882 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5883 // this r value looks like a 'dot' particle, fading sharply to
5884 // black at the edges
5885 // (probably not realistic but looks good enough)
5886 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5887 //r = brighten/(range*2+1);
5888 r = brighten / (range * 2 + 1);
5890 r *= (1 - x*x/(float)(range*range));
5891 GL_Color(r, r, r, 1);
5892 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5893 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5894 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5895 GL_BlendFunc(GL_ONE, GL_ONE);
5898 // copy the vertically blurred bloom view to a texture
5899 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);
5900 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5904 void R_HDR_RenderBloomTexture(void)
5906 int oldwidth, oldheight;
5907 float oldcolorscale;
5908 qboolean oldwaterstate;
5910 oldwaterstate = r_waterstate.enabled;
5911 oldcolorscale = r_refdef.view.colorscale;
5912 oldwidth = r_refdef.view.width;
5913 oldheight = r_refdef.view.height;
5914 r_refdef.view.width = r_bloomstate.bloomwidth;
5915 r_refdef.view.height = r_bloomstate.bloomheight;
5917 if(r_hdr.integer < 2)
5918 r_waterstate.enabled = false;
5920 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5921 // TODO: add exposure compensation features
5922 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5924 r_refdef.view.showdebug = false;
5925 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5927 R_ResetViewRendering3D();
5929 R_ClearScreen(r_refdef.fogenabled);
5930 if (r_timereport_active)
5931 R_TimeReport("HDRclear");
5934 if (r_timereport_active)
5935 R_TimeReport("visibility");
5937 // only do secondary renders with HDR if r_hdr is 2 or higher
5938 r_waterstate.numwaterplanes = 0;
5939 if (r_waterstate.enabled)
5940 R_RenderWaterPlanes();
5942 r_refdef.view.showdebug = true;
5944 r_waterstate.numwaterplanes = 0;
5946 R_ResetViewRendering2D();
5948 R_Bloom_CopyHDRTexture();
5949 R_Bloom_MakeTexture();
5951 // restore the view settings
5952 r_waterstate.enabled = oldwaterstate;
5953 r_refdef.view.width = oldwidth;
5954 r_refdef.view.height = oldheight;
5955 r_refdef.view.colorscale = oldcolorscale;
5957 R_ResetViewRendering3D();
5959 R_ClearScreen(r_refdef.fogenabled);
5960 if (r_timereport_active)
5961 R_TimeReport("viewclear");
5964 static void R_BlendView(void)
5966 unsigned int permutation;
5967 float uservecs[4][4];
5969 switch (vid.renderpath)
5971 case RENDERPATH_GL20:
5972 case RENDERPATH_D3D9:
5973 case RENDERPATH_D3D10:
5974 case RENDERPATH_D3D11:
5975 case RENDERPATH_SOFT:
5976 case RENDERPATH_GLES2:
5978 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5979 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5980 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5981 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5982 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5984 if (r_bloomstate.texture_screen)
5986 // make sure the buffer is available
5987 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5989 R_ResetViewRendering2D();
5991 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5993 // declare variables
5995 static float avgspeed;
5997 speed = VectorLength(cl.movement_velocity);
5999 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6000 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6002 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6003 speed = bound(0, speed, 1);
6004 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6006 // calculate values into a standard alpha
6007 cl.motionbluralpha = 1 - exp(-
6009 (r_motionblur.value * speed / 80)
6011 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6014 max(0.0001, cl.time - cl.oldtime) // fps independent
6017 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6018 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6020 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6022 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6023 GL_Color(1, 1, 1, cl.motionbluralpha);
6024 switch(vid.renderpath)
6026 case RENDERPATH_GL11:
6027 case RENDERPATH_GL13:
6028 case RENDERPATH_GL20:
6029 case RENDERPATH_SOFT:
6030 case RENDERPATH_GLES2:
6031 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6033 case RENDERPATH_D3D9:
6034 case RENDERPATH_D3D10:
6035 case RENDERPATH_D3D11:
6036 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6039 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6040 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6041 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6045 // copy view into the screen texture
6046 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);
6047 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6049 else if (!r_bloomstate.texture_bloom)
6051 // we may still have to do view tint...
6052 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6054 // apply a color tint to the whole view
6055 R_ResetViewRendering2D();
6056 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6057 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6058 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6059 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6060 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6062 break; // no screen processing, no bloom, skip it
6065 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6067 // render simple bloom effect
6068 // copy the screen and shrink it and darken it for the bloom process
6069 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6070 // make the bloom texture
6071 R_Bloom_MakeTexture();
6074 #if _MSC_VER >= 1400
6075 #define sscanf sscanf_s
6077 memset(uservecs, 0, sizeof(uservecs));
6078 if (r_glsl_postprocess_uservec1_enable.integer)
6079 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6080 if (r_glsl_postprocess_uservec2_enable.integer)
6081 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6082 if (r_glsl_postprocess_uservec3_enable.integer)
6083 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6084 if (r_glsl_postprocess_uservec4_enable.integer)
6085 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6087 R_ResetViewRendering2D();
6088 GL_Color(1, 1, 1, 1);
6089 GL_BlendFunc(GL_ONE, GL_ZERO);
6091 switch(vid.renderpath)
6093 case RENDERPATH_GL20:
6094 case RENDERPATH_GLES2:
6095 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6096 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6097 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6098 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6099 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6100 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]);
6101 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6102 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]);
6103 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]);
6104 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]);
6105 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]);
6106 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6107 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6108 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);
6110 case RENDERPATH_D3D9:
6112 // 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...
6113 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6114 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6115 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6116 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6117 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6118 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6119 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6120 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6121 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6122 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6123 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6124 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6125 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6126 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6129 case RENDERPATH_D3D10:
6130 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6132 case RENDERPATH_D3D11:
6133 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6135 case RENDERPATH_SOFT:
6136 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6137 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6138 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6139 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6140 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6141 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6142 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6143 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6144 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6145 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6146 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6147 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6148 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6149 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6154 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6155 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6157 case RENDERPATH_GL13:
6158 case RENDERPATH_GL11:
6159 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6161 // apply a color tint to the whole view
6162 R_ResetViewRendering2D();
6163 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6164 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6165 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6166 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6167 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6173 matrix4x4_t r_waterscrollmatrix;
6175 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6177 if (r_refdef.fog_density)
6179 r_refdef.fogcolor[0] = r_refdef.fog_red;
6180 r_refdef.fogcolor[1] = r_refdef.fog_green;
6181 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6183 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6184 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6185 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6186 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6190 VectorCopy(r_refdef.fogcolor, fogvec);
6191 // color.rgb *= ContrastBoost * SceneBrightness;
6192 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6193 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6194 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6195 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6200 void R_UpdateVariables(void)
6204 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6206 r_refdef.farclip = r_farclip_base.value;
6207 if (r_refdef.scene.worldmodel)
6208 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6209 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6211 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6212 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6213 r_refdef.polygonfactor = 0;
6214 r_refdef.polygonoffset = 0;
6215 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6216 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6218 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6219 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6220 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6221 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6222 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6223 if (FAKELIGHT_ENABLED)
6225 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6227 if (r_showsurfaces.integer)
6229 r_refdef.scene.rtworld = false;
6230 r_refdef.scene.rtworldshadows = false;
6231 r_refdef.scene.rtdlight = false;
6232 r_refdef.scene.rtdlightshadows = false;
6233 r_refdef.lightmapintensity = 0;
6236 if (gamemode == GAME_NEHAHRA)
6238 if (gl_fogenable.integer)
6240 r_refdef.oldgl_fogenable = true;
6241 r_refdef.fog_density = gl_fogdensity.value;
6242 r_refdef.fog_red = gl_fogred.value;
6243 r_refdef.fog_green = gl_foggreen.value;
6244 r_refdef.fog_blue = gl_fogblue.value;
6245 r_refdef.fog_alpha = 1;
6246 r_refdef.fog_start = 0;
6247 r_refdef.fog_end = gl_skyclip.value;
6248 r_refdef.fog_height = 1<<30;
6249 r_refdef.fog_fadedepth = 128;
6251 else if (r_refdef.oldgl_fogenable)
6253 r_refdef.oldgl_fogenable = false;
6254 r_refdef.fog_density = 0;
6255 r_refdef.fog_red = 0;
6256 r_refdef.fog_green = 0;
6257 r_refdef.fog_blue = 0;
6258 r_refdef.fog_alpha = 0;
6259 r_refdef.fog_start = 0;
6260 r_refdef.fog_end = 0;
6261 r_refdef.fog_height = 1<<30;
6262 r_refdef.fog_fadedepth = 128;
6266 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6267 r_refdef.fog_start = max(0, r_refdef.fog_start);
6268 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6270 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6272 if (r_refdef.fog_density && r_drawfog.integer)
6274 r_refdef.fogenabled = true;
6275 // this is the point where the fog reaches 0.9986 alpha, which we
6276 // consider a good enough cutoff point for the texture
6277 // (0.9986 * 256 == 255.6)
6278 if (r_fog_exp2.integer)
6279 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6281 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6282 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6283 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6284 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6285 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6286 R_BuildFogHeightTexture();
6287 // fog color was already set
6288 // update the fog texture
6289 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)
6290 R_BuildFogTexture();
6291 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6292 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6295 r_refdef.fogenabled = false;
6297 switch(vid.renderpath)
6299 case RENDERPATH_GL20:
6300 case RENDERPATH_D3D9:
6301 case RENDERPATH_D3D10:
6302 case RENDERPATH_D3D11:
6303 case RENDERPATH_SOFT:
6304 case RENDERPATH_GLES2:
6305 if(v_glslgamma.integer && !vid_gammatables_trivial)
6307 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6309 // build GLSL gamma texture
6310 #define RAMPWIDTH 256
6311 unsigned short ramp[RAMPWIDTH * 3];
6312 unsigned char rampbgr[RAMPWIDTH][4];
6315 r_texture_gammaramps_serial = vid_gammatables_serial;
6317 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6318 for(i = 0; i < RAMPWIDTH; ++i)
6320 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6321 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6322 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6325 if (r_texture_gammaramps)
6327 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6331 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6337 // remove GLSL gamma texture
6340 case RENDERPATH_GL13:
6341 case RENDERPATH_GL11:
6346 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6347 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6353 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6354 if( scenetype != r_currentscenetype ) {
6355 // store the old scenetype
6356 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6357 r_currentscenetype = scenetype;
6358 // move in the new scene
6359 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6368 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6370 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6371 if( scenetype == r_currentscenetype ) {
6372 return &r_refdef.scene;
6374 return &r_scenes_store[ scenetype ];
6383 int dpsoftrast_test;
6384 void R_RenderView(void)
6386 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6388 dpsoftrast_test = r_test.integer;
6390 if (r_timereport_active)
6391 R_TimeReport("start");
6392 r_textureframe++; // used only by R_GetCurrentTexture
6393 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6395 if(R_CompileShader_CheckStaticParms())
6398 if (!r_drawentities.integer)
6399 r_refdef.scene.numentities = 0;
6401 R_AnimCache_ClearCache();
6402 R_FrameData_NewFrame();
6404 /* adjust for stereo display */
6405 if(R_Stereo_Active())
6407 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);
6408 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6411 if (r_refdef.view.isoverlay)
6413 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6414 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6415 R_TimeReport("depthclear");
6417 r_refdef.view.showdebug = false;
6419 r_waterstate.enabled = false;
6420 r_waterstate.numwaterplanes = 0;
6424 r_refdef.view.matrix = originalmatrix;
6430 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6432 r_refdef.view.matrix = originalmatrix;
6433 return; //Host_Error ("R_RenderView: NULL worldmodel");
6436 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6438 R_RenderView_UpdateViewVectors();
6440 R_Shadow_UpdateWorldLightSelection();
6442 R_Bloom_StartFrame();
6443 R_Water_StartFrame();
6446 if (r_timereport_active)
6447 R_TimeReport("viewsetup");
6449 R_ResetViewRendering3D();
6451 if (r_refdef.view.clear || r_refdef.fogenabled)
6453 R_ClearScreen(r_refdef.fogenabled);
6454 if (r_timereport_active)
6455 R_TimeReport("viewclear");
6457 r_refdef.view.clear = true;
6459 // this produces a bloom texture to be used in R_BlendView() later
6460 if (r_hdr.integer && r_bloomstate.bloomwidth)
6462 R_HDR_RenderBloomTexture();
6463 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6464 r_textureframe++; // used only by R_GetCurrentTexture
6467 r_refdef.view.showdebug = true;
6470 if (r_timereport_active)
6471 R_TimeReport("visibility");
6473 r_waterstate.numwaterplanes = 0;
6474 if (r_waterstate.enabled)
6475 R_RenderWaterPlanes();
6478 r_waterstate.numwaterplanes = 0;
6481 if (r_timereport_active)
6482 R_TimeReport("blendview");
6484 GL_Scissor(0, 0, vid.width, vid.height);
6485 GL_ScissorTest(false);
6487 r_refdef.view.matrix = originalmatrix;
6492 void R_RenderWaterPlanes(void)
6494 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6496 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6497 if (r_timereport_active)
6498 R_TimeReport("waterworld");
6501 // don't let sound skip if going slow
6502 if (r_refdef.scene.extraupdate)
6505 R_DrawModelsAddWaterPlanes();
6506 if (r_timereport_active)
6507 R_TimeReport("watermodels");
6509 if (r_waterstate.numwaterplanes)
6511 R_Water_ProcessPlanes();
6512 if (r_timereport_active)
6513 R_TimeReport("waterscenes");
6517 extern void R_DrawLightningBeams (void);
6518 extern void VM_CL_AddPolygonsToMeshQueue (void);
6519 extern void R_DrawPortals (void);
6520 extern cvar_t cl_locs_show;
6521 static void R_DrawLocs(void);
6522 static void R_DrawEntityBBoxes(void);
6523 static void R_DrawModelDecals(void);
6524 extern void R_DrawModelShadows(void);
6525 extern void R_DrawModelShadowMaps(void);
6526 extern cvar_t cl_decals_newsystem;
6527 extern qboolean r_shadow_usingdeferredprepass;
6528 void R_RenderScene(void)
6530 qboolean shadowmapping = false;
6532 if (r_timereport_active)
6533 R_TimeReport("beginscene");
6535 r_refdef.stats.renders++;
6539 // don't let sound skip if going slow
6540 if (r_refdef.scene.extraupdate)
6543 R_MeshQueue_BeginScene();
6547 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);
6549 if (r_timereport_active)
6550 R_TimeReport("skystartframe");
6552 if (cl.csqc_vidvars.drawworld)
6554 // don't let sound skip if going slow
6555 if (r_refdef.scene.extraupdate)
6558 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6560 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6561 if (r_timereport_active)
6562 R_TimeReport("worldsky");
6565 if (R_DrawBrushModelsSky() && r_timereport_active)
6566 R_TimeReport("bmodelsky");
6568 if (skyrendermasked && skyrenderlater)
6570 // we have to force off the water clipping plane while rendering sky
6574 if (r_timereport_active)
6575 R_TimeReport("sky");
6579 R_AnimCache_CacheVisibleEntities();
6580 if (r_timereport_active)
6581 R_TimeReport("animation");
6583 R_Shadow_PrepareLights();
6584 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6585 R_Shadow_PrepareModelShadows();
6586 if (r_timereport_active)
6587 R_TimeReport("preparelights");
6589 if (R_Shadow_ShadowMappingEnabled())
6590 shadowmapping = true;
6592 if (r_shadow_usingdeferredprepass)
6593 R_Shadow_DrawPrepass();
6595 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6597 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6598 if (r_timereport_active)
6599 R_TimeReport("worlddepth");
6601 if (r_depthfirst.integer >= 2)
6603 R_DrawModelsDepth();
6604 if (r_timereport_active)
6605 R_TimeReport("modeldepth");
6608 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6610 R_DrawModelShadowMaps();
6611 R_ResetViewRendering3D();
6612 // don't let sound skip if going slow
6613 if (r_refdef.scene.extraupdate)
6617 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6619 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6620 if (r_timereport_active)
6621 R_TimeReport("world");
6624 // don't let sound skip if going slow
6625 if (r_refdef.scene.extraupdate)
6629 if (r_timereport_active)
6630 R_TimeReport("models");
6632 // don't let sound skip if going slow
6633 if (r_refdef.scene.extraupdate)
6636 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6638 R_DrawModelShadows();
6639 R_ResetViewRendering3D();
6640 // don't let sound skip if going slow
6641 if (r_refdef.scene.extraupdate)
6645 if (!r_shadow_usingdeferredprepass)
6647 R_Shadow_DrawLights();
6648 if (r_timereport_active)
6649 R_TimeReport("rtlights");
6652 // don't let sound skip if going slow
6653 if (r_refdef.scene.extraupdate)
6656 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6658 R_DrawModelShadows();
6659 R_ResetViewRendering3D();
6660 // don't let sound skip if going slow
6661 if (r_refdef.scene.extraupdate)
6665 if (cl.csqc_vidvars.drawworld)
6667 if (cl_decals_newsystem.integer)
6669 R_DrawModelDecals();
6670 if (r_timereport_active)
6671 R_TimeReport("modeldecals");
6676 if (r_timereport_active)
6677 R_TimeReport("decals");
6681 if (r_timereport_active)
6682 R_TimeReport("particles");
6685 if (r_timereport_active)
6686 R_TimeReport("explosions");
6688 R_DrawLightningBeams();
6689 if (r_timereport_active)
6690 R_TimeReport("lightning");
6693 VM_CL_AddPolygonsToMeshQueue();
6695 if (r_refdef.view.showdebug)
6697 if (cl_locs_show.integer)
6700 if (r_timereport_active)
6701 R_TimeReport("showlocs");
6704 if (r_drawportals.integer)
6707 if (r_timereport_active)
6708 R_TimeReport("portals");
6711 if (r_showbboxes.value > 0)
6713 R_DrawEntityBBoxes();
6714 if (r_timereport_active)
6715 R_TimeReport("bboxes");
6719 R_MeshQueue_RenderTransparent();
6720 if (r_timereport_active)
6721 R_TimeReport("drawtrans");
6723 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))
6725 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6726 if (r_timereport_active)
6727 R_TimeReport("worlddebug");
6728 R_DrawModelsDebug();
6729 if (r_timereport_active)
6730 R_TimeReport("modeldebug");
6733 if (cl.csqc_vidvars.drawworld)
6735 R_Shadow_DrawCoronas();
6736 if (r_timereport_active)
6737 R_TimeReport("coronas");
6742 GL_DepthTest(false);
6743 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6744 GL_Color(1, 1, 1, 1);
6745 qglBegin(GL_POLYGON);
6746 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6747 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6748 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6749 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6751 qglBegin(GL_POLYGON);
6752 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]);
6753 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]);
6754 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]);
6755 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]);
6757 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6761 // don't let sound skip if going slow
6762 if (r_refdef.scene.extraupdate)
6765 R_ResetViewRendering2D();
6768 static const unsigned short bboxelements[36] =
6778 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6781 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6783 RSurf_ActiveWorldEntity();
6785 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6786 GL_DepthMask(false);
6787 GL_DepthRange(0, 1);
6788 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6789 // R_Mesh_ResetTextureState();
6791 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6792 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6793 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6794 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6795 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6796 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6797 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6798 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6799 R_FillColors(color4f, 8, cr, cg, cb, ca);
6800 if (r_refdef.fogenabled)
6802 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6804 f1 = RSurf_FogVertex(v);
6806 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6807 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6808 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6811 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6812 R_Mesh_ResetTextureState();
6813 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6814 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6817 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6821 prvm_edict_t *edict;
6822 prvm_prog_t *prog_save = prog;
6824 // this function draws bounding boxes of server entities
6828 GL_CullFace(GL_NONE);
6829 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6833 for (i = 0;i < numsurfaces;i++)
6835 edict = PRVM_EDICT_NUM(surfacelist[i]);
6836 switch ((int)edict->fields.server->solid)
6838 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6839 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6840 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6841 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6842 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6843 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6845 color[3] *= r_showbboxes.value;
6846 color[3] = bound(0, color[3], 1);
6847 GL_DepthTest(!r_showdisabledepthtest.integer);
6848 GL_CullFace(r_refdef.view.cullface_front);
6849 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6855 static void R_DrawEntityBBoxes(void)
6858 prvm_edict_t *edict;
6860 prvm_prog_t *prog_save = prog;
6862 // this function draws bounding boxes of server entities
6868 for (i = 0;i < prog->num_edicts;i++)
6870 edict = PRVM_EDICT_NUM(i);
6871 if (edict->priv.server->free)
6873 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6874 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6876 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6878 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6879 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6885 static const int nomodelelement3i[24] =
6897 static const unsigned short nomodelelement3s[24] =
6909 static const float nomodelvertex3f[6*3] =
6919 static const float nomodelcolor4f[6*4] =
6921 0.0f, 0.0f, 0.5f, 1.0f,
6922 0.0f, 0.0f, 0.5f, 1.0f,
6923 0.0f, 0.5f, 0.0f, 1.0f,
6924 0.0f, 0.5f, 0.0f, 1.0f,
6925 0.5f, 0.0f, 0.0f, 1.0f,
6926 0.5f, 0.0f, 0.0f, 1.0f
6929 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6935 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);
6937 // this is only called once per entity so numsurfaces is always 1, and
6938 // surfacelist is always {0}, so this code does not handle batches
6940 if (rsurface.ent_flags & RENDER_ADDITIVE)
6942 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6943 GL_DepthMask(false);
6945 else if (rsurface.colormod[3] < 1)
6947 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6948 GL_DepthMask(false);
6952 GL_BlendFunc(GL_ONE, GL_ZERO);
6955 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6956 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6957 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6958 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6959 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6960 for (i = 0, c = color4f;i < 6;i++, c += 4)
6962 c[0] *= rsurface.colormod[0];
6963 c[1] *= rsurface.colormod[1];
6964 c[2] *= rsurface.colormod[2];
6965 c[3] *= rsurface.colormod[3];
6967 if (r_refdef.fogenabled)
6969 for (i = 0, c = color4f;i < 6;i++, c += 4)
6971 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6973 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6974 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6975 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6978 // R_Mesh_ResetTextureState();
6979 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6980 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6981 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6984 void R_DrawNoModel(entity_render_t *ent)
6987 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6988 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6989 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6991 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6994 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6996 vec3_t right1, right2, diff, normal;
6998 VectorSubtract (org2, org1, normal);
7000 // calculate 'right' vector for start
7001 VectorSubtract (r_refdef.view.origin, org1, diff);
7002 CrossProduct (normal, diff, right1);
7003 VectorNormalize (right1);
7005 // calculate 'right' vector for end
7006 VectorSubtract (r_refdef.view.origin, org2, diff);
7007 CrossProduct (normal, diff, right2);
7008 VectorNormalize (right2);
7010 vert[ 0] = org1[0] + width * right1[0];
7011 vert[ 1] = org1[1] + width * right1[1];
7012 vert[ 2] = org1[2] + width * right1[2];
7013 vert[ 3] = org1[0] - width * right1[0];
7014 vert[ 4] = org1[1] - width * right1[1];
7015 vert[ 5] = org1[2] - width * right1[2];
7016 vert[ 6] = org2[0] - width * right2[0];
7017 vert[ 7] = org2[1] - width * right2[1];
7018 vert[ 8] = org2[2] - width * right2[2];
7019 vert[ 9] = org2[0] + width * right2[0];
7020 vert[10] = org2[1] + width * right2[1];
7021 vert[11] = org2[2] + width * right2[2];
7024 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)
7026 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7027 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7028 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7029 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7030 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7031 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7032 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7033 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7034 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7035 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7036 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7037 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7040 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7045 VectorSet(v, x, y, z);
7046 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7047 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7049 if (i == mesh->numvertices)
7051 if (mesh->numvertices < mesh->maxvertices)
7053 VectorCopy(v, vertex3f);
7054 mesh->numvertices++;
7056 return mesh->numvertices;
7062 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7066 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7067 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7068 e = mesh->element3i + mesh->numtriangles * 3;
7069 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7071 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7072 if (mesh->numtriangles < mesh->maxtriangles)
7077 mesh->numtriangles++;
7079 element[1] = element[2];
7083 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7087 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7088 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7089 e = mesh->element3i + mesh->numtriangles * 3;
7090 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7092 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7093 if (mesh->numtriangles < mesh->maxtriangles)
7098 mesh->numtriangles++;
7100 element[1] = element[2];
7104 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7105 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7107 int planenum, planenum2;
7110 mplane_t *plane, *plane2;
7112 double temppoints[2][256*3];
7113 // figure out how large a bounding box we need to properly compute this brush
7115 for (w = 0;w < numplanes;w++)
7116 maxdist = max(maxdist, fabs(planes[w].dist));
7117 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7118 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7119 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7123 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7124 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7126 if (planenum2 == planenum)
7128 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);
7131 if (tempnumpoints < 3)
7133 // generate elements forming a triangle fan for this polygon
7134 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7138 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)
7140 texturelayer_t *layer;
7141 layer = t->currentlayers + t->currentnumlayers++;
7143 layer->depthmask = depthmask;
7144 layer->blendfunc1 = blendfunc1;
7145 layer->blendfunc2 = blendfunc2;
7146 layer->texture = texture;
7147 layer->texmatrix = *matrix;
7148 layer->color[0] = r;
7149 layer->color[1] = g;
7150 layer->color[2] = b;
7151 layer->color[3] = a;
7154 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7156 if(parms[0] == 0 && parms[1] == 0)
7158 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7159 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7164 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7167 index = parms[2] + r_refdef.scene.time * parms[3];
7168 index -= floor(index);
7169 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7172 case Q3WAVEFUNC_NONE:
7173 case Q3WAVEFUNC_NOISE:
7174 case Q3WAVEFUNC_COUNT:
7177 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7178 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7179 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7180 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7181 case Q3WAVEFUNC_TRIANGLE:
7183 f = index - floor(index);
7194 f = parms[0] + parms[1] * f;
7195 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7196 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7200 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7205 matrix4x4_t matrix, temp;
7206 switch(tcmod->tcmod)
7210 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7211 matrix = r_waterscrollmatrix;
7213 matrix = identitymatrix;
7215 case Q3TCMOD_ENTITYTRANSLATE:
7216 // this is used in Q3 to allow the gamecode to control texcoord
7217 // scrolling on the entity, which is not supported in darkplaces yet.
7218 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7220 case Q3TCMOD_ROTATE:
7221 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7222 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7223 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7226 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7228 case Q3TCMOD_SCROLL:
7229 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7231 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7232 w = (int) tcmod->parms[0];
7233 h = (int) tcmod->parms[1];
7234 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7236 idx = (int) floor(f * w * h);
7237 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7239 case Q3TCMOD_STRETCH:
7240 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7241 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7243 case Q3TCMOD_TRANSFORM:
7244 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7245 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7246 VectorSet(tcmat + 6, 0 , 0 , 1);
7247 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7248 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7250 case Q3TCMOD_TURBULENT:
7251 // this is handled in the RSurf_PrepareVertices function
7252 matrix = identitymatrix;
7256 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7259 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7261 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7262 char name[MAX_QPATH];
7263 skinframe_t *skinframe;
7264 unsigned char pixels[296*194];
7265 strlcpy(cache->name, skinname, sizeof(cache->name));
7266 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7267 if (developer_loading.integer)
7268 Con_Printf("loading %s\n", name);
7269 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7270 if (!skinframe || !skinframe->base)
7273 fs_offset_t filesize;
7275 f = FS_LoadFile(name, tempmempool, true, &filesize);
7278 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7279 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7283 cache->skinframe = skinframe;
7286 texture_t *R_GetCurrentTexture(texture_t *t)
7289 const entity_render_t *ent = rsurface.entity;
7290 dp_model_t *model = ent->model;
7291 q3shaderinfo_layer_tcmod_t *tcmod;
7293 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7294 return t->currentframe;
7295 t->update_lastrenderframe = r_textureframe;
7296 t->update_lastrenderentity = (void *)ent;
7298 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7299 t->camera_entity = ent->entitynumber;
7301 t->camera_entity = 0;
7303 // switch to an alternate material if this is a q1bsp animated material
7305 texture_t *texture = t;
7306 int s = rsurface.ent_skinnum;
7307 if ((unsigned int)s >= (unsigned int)model->numskins)
7309 if (model->skinscenes)
7311 if (model->skinscenes[s].framecount > 1)
7312 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7314 s = model->skinscenes[s].firstframe;
7317 t = t + s * model->num_surfaces;
7320 // use an alternate animation if the entity's frame is not 0,
7321 // and only if the texture has an alternate animation
7322 if (rsurface.ent_alttextures && t->anim_total[1])
7323 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7325 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7327 texture->currentframe = t;
7330 // update currentskinframe to be a qw skin or animation frame
7331 if (rsurface.ent_qwskin >= 0)
7333 i = rsurface.ent_qwskin;
7334 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7336 r_qwskincache_size = cl.maxclients;
7338 Mem_Free(r_qwskincache);
7339 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7341 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7342 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7343 t->currentskinframe = r_qwskincache[i].skinframe;
7344 if (t->currentskinframe == NULL)
7345 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7347 else if (t->numskinframes >= 2)
7348 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7349 if (t->backgroundnumskinframes >= 2)
7350 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7352 t->currentmaterialflags = t->basematerialflags;
7353 t->currentalpha = rsurface.colormod[3];
7354 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7355 t->currentalpha *= r_wateralpha.value;
7356 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7357 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7358 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7359 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7360 if (!(rsurface.ent_flags & RENDER_LIGHT))
7361 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7362 else if (FAKELIGHT_ENABLED)
7364 // no modellight if using fakelight for the map
7366 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7368 // pick a model lighting mode
7369 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7370 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7372 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7374 if (rsurface.ent_flags & RENDER_ADDITIVE)
7375 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7376 else if (t->currentalpha < 1)
7377 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7378 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7379 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7380 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7381 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7382 if (t->backgroundnumskinframes)
7383 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7384 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7386 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7387 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7390 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7391 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7392 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7394 // there is no tcmod
7395 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7397 t->currenttexmatrix = r_waterscrollmatrix;
7398 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7400 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7402 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7403 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7406 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7407 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7408 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7409 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7411 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7412 if (t->currentskinframe->qpixels)
7413 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7414 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7415 if (!t->basetexture)
7416 t->basetexture = r_texture_notexture;
7417 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7418 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7419 t->nmaptexture = t->currentskinframe->nmap;
7420 if (!t->nmaptexture)
7421 t->nmaptexture = r_texture_blanknormalmap;
7422 t->glosstexture = r_texture_black;
7423 t->glowtexture = t->currentskinframe->glow;
7424 t->fogtexture = t->currentskinframe->fog;
7425 t->reflectmasktexture = t->currentskinframe->reflect;
7426 if (t->backgroundnumskinframes)
7428 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7429 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7430 t->backgroundglosstexture = r_texture_black;
7431 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7432 if (!t->backgroundnmaptexture)
7433 t->backgroundnmaptexture = r_texture_blanknormalmap;
7437 t->backgroundbasetexture = r_texture_white;
7438 t->backgroundnmaptexture = r_texture_blanknormalmap;
7439 t->backgroundglosstexture = r_texture_black;
7440 t->backgroundglowtexture = NULL;
7442 t->specularpower = r_shadow_glossexponent.value;
7443 // TODO: store reference values for these in the texture?
7444 t->specularscale = 0;
7445 if (r_shadow_gloss.integer > 0)
7447 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7449 if (r_shadow_glossintensity.value > 0)
7451 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7452 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7453 t->specularscale = r_shadow_glossintensity.value;
7456 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7458 t->glosstexture = r_texture_white;
7459 t->backgroundglosstexture = r_texture_white;
7460 t->specularscale = r_shadow_gloss2intensity.value;
7461 t->specularpower = r_shadow_gloss2exponent.value;
7464 t->specularscale *= t->specularscalemod;
7465 t->specularpower *= t->specularpowermod;
7467 // lightmaps mode looks bad with dlights using actual texturing, so turn
7468 // off the colormap and glossmap, but leave the normalmap on as it still
7469 // accurately represents the shading involved
7470 if (gl_lightmaps.integer)
7472 t->basetexture = r_texture_grey128;
7473 t->pantstexture = r_texture_black;
7474 t->shirttexture = r_texture_black;
7475 t->nmaptexture = r_texture_blanknormalmap;
7476 t->glosstexture = r_texture_black;
7477 t->glowtexture = NULL;
7478 t->fogtexture = NULL;
7479 t->reflectmasktexture = NULL;
7480 t->backgroundbasetexture = NULL;
7481 t->backgroundnmaptexture = r_texture_blanknormalmap;
7482 t->backgroundglosstexture = r_texture_black;
7483 t->backgroundglowtexture = NULL;
7484 t->specularscale = 0;
7485 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7488 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7489 VectorClear(t->dlightcolor);
7490 t->currentnumlayers = 0;
7491 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7493 int blendfunc1, blendfunc2;
7495 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7497 blendfunc1 = GL_SRC_ALPHA;
7498 blendfunc2 = GL_ONE;
7500 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7502 blendfunc1 = GL_SRC_ALPHA;
7503 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7505 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7507 blendfunc1 = t->customblendfunc[0];
7508 blendfunc2 = t->customblendfunc[1];
7512 blendfunc1 = GL_ONE;
7513 blendfunc2 = GL_ZERO;
7515 // don't colormod evilblend textures
7516 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7517 VectorSet(t->lightmapcolor, 1, 1, 1);
7518 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7519 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7521 // fullbright is not affected by r_refdef.lightmapintensity
7522 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]);
7523 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7524 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]);
7525 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7526 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]);
7530 vec3_t ambientcolor;
7532 // set the color tint used for lights affecting this surface
7533 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7535 // q3bsp has no lightmap updates, so the lightstylevalue that
7536 // would normally be baked into the lightmap must be
7537 // applied to the color
7538 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7539 if (model->type == mod_brushq3)
7540 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7541 colorscale *= r_refdef.lightmapintensity;
7542 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7543 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7544 // basic lit geometry
7545 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]);
7546 // add pants/shirt if needed
7547 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7548 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]);
7549 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7550 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]);
7551 // now add ambient passes if needed
7552 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7554 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]);
7555 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7556 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]);
7557 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7558 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]);
7561 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7562 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]);
7563 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7565 // if this is opaque use alpha blend which will darken the earlier
7568 // if this is an alpha blended material, all the earlier passes
7569 // were darkened by fog already, so we only need to add the fog
7570 // color ontop through the fog mask texture
7572 // if this is an additive blended material, all the earlier passes
7573 // were darkened by fog already, and we should not add fog color
7574 // (because the background was not darkened, there is no fog color
7575 // that was lost behind it).
7576 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]);
7580 return t->currentframe;
7583 rsurfacestate_t rsurface;
7585 void RSurf_ActiveWorldEntity(void)
7587 dp_model_t *model = r_refdef.scene.worldmodel;
7588 //if (rsurface.entity == r_refdef.scene.worldentity)
7590 rsurface.entity = r_refdef.scene.worldentity;
7591 rsurface.skeleton = NULL;
7592 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7593 rsurface.ent_skinnum = 0;
7594 rsurface.ent_qwskin = -1;
7595 rsurface.ent_shadertime = 0;
7596 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7597 rsurface.matrix = identitymatrix;
7598 rsurface.inversematrix = identitymatrix;
7599 rsurface.matrixscale = 1;
7600 rsurface.inversematrixscale = 1;
7601 R_EntityMatrix(&identitymatrix);
7602 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7603 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7604 rsurface.fograngerecip = r_refdef.fograngerecip;
7605 rsurface.fogheightfade = r_refdef.fogheightfade;
7606 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7607 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7608 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7609 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7610 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7611 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7612 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7613 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7614 rsurface.colormod[3] = 1;
7615 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);
7616 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7617 rsurface.frameblend[0].lerp = 1;
7618 rsurface.ent_alttextures = false;
7619 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7620 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7621 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7622 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7623 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7624 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7625 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7627 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7628 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7630 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7631 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7632 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7633 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7634 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7635 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7636 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7637 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7638 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7639 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7640 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7641 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7642 rsurface.modelelement3i = model->surfmesh.data_element3i;
7643 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7644 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7645 rsurface.modelelement3s = model->surfmesh.data_element3s;
7646 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7647 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7648 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7649 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7650 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7651 rsurface.modelsurfaces = model->data_surfaces;
7652 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7653 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7654 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7655 rsurface.modelgeneratedvertex = false;
7656 rsurface.batchgeneratedvertex = false;
7657 rsurface.batchfirstvertex = 0;
7658 rsurface.batchnumvertices = 0;
7659 rsurface.batchfirsttriangle = 0;
7660 rsurface.batchnumtriangles = 0;
7661 rsurface.batchvertex3f = NULL;
7662 rsurface.batchvertex3f_vertexbuffer = NULL;
7663 rsurface.batchvertex3f_bufferoffset = 0;
7664 rsurface.batchsvector3f = NULL;
7665 rsurface.batchsvector3f_vertexbuffer = NULL;
7666 rsurface.batchsvector3f_bufferoffset = 0;
7667 rsurface.batchtvector3f = NULL;
7668 rsurface.batchtvector3f_vertexbuffer = NULL;
7669 rsurface.batchtvector3f_bufferoffset = 0;
7670 rsurface.batchnormal3f = NULL;
7671 rsurface.batchnormal3f_vertexbuffer = NULL;
7672 rsurface.batchnormal3f_bufferoffset = 0;
7673 rsurface.batchlightmapcolor4f = NULL;
7674 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7675 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7676 rsurface.batchtexcoordtexture2f = NULL;
7677 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7678 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7679 rsurface.batchtexcoordlightmap2f = NULL;
7680 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7681 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7682 rsurface.batchvertexmesh = NULL;
7683 rsurface.batchvertexmeshbuffer = NULL;
7684 rsurface.batchvertex3fbuffer = NULL;
7685 rsurface.batchelement3i = NULL;
7686 rsurface.batchelement3i_indexbuffer = NULL;
7687 rsurface.batchelement3i_bufferoffset = 0;
7688 rsurface.batchelement3s = NULL;
7689 rsurface.batchelement3s_indexbuffer = NULL;
7690 rsurface.batchelement3s_bufferoffset = 0;
7691 rsurface.passcolor4f = NULL;
7692 rsurface.passcolor4f_vertexbuffer = NULL;
7693 rsurface.passcolor4f_bufferoffset = 0;
7696 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7698 dp_model_t *model = ent->model;
7699 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7701 rsurface.entity = (entity_render_t *)ent;
7702 rsurface.skeleton = ent->skeleton;
7703 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7704 rsurface.ent_skinnum = ent->skinnum;
7705 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;
7706 rsurface.ent_shadertime = ent->shadertime;
7707 rsurface.ent_flags = ent->flags;
7708 rsurface.matrix = ent->matrix;
7709 rsurface.inversematrix = ent->inversematrix;
7710 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7711 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7712 R_EntityMatrix(&rsurface.matrix);
7713 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7714 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7715 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7716 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7717 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7718 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7719 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7720 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7721 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7722 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7723 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7724 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7725 rsurface.colormod[3] = ent->alpha;
7726 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7727 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7728 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7729 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7730 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7731 if (ent->model->brush.submodel && !prepass)
7733 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7734 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7736 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7738 if (ent->animcache_vertex3f)
7740 rsurface.modelvertex3f = ent->animcache_vertex3f;
7741 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7742 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7743 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7744 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7745 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7746 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7748 else if (wanttangents)
7750 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7751 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7752 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7753 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7754 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7755 rsurface.modelvertexmesh = NULL;
7756 rsurface.modelvertexmeshbuffer = NULL;
7757 rsurface.modelvertex3fbuffer = NULL;
7759 else if (wantnormals)
7761 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7762 rsurface.modelsvector3f = NULL;
7763 rsurface.modeltvector3f = NULL;
7764 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7765 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7766 rsurface.modelvertexmesh = NULL;
7767 rsurface.modelvertexmeshbuffer = NULL;
7768 rsurface.modelvertex3fbuffer = NULL;
7772 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7773 rsurface.modelsvector3f = NULL;
7774 rsurface.modeltvector3f = NULL;
7775 rsurface.modelnormal3f = NULL;
7776 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7777 rsurface.modelvertexmesh = NULL;
7778 rsurface.modelvertexmeshbuffer = NULL;
7779 rsurface.modelvertex3fbuffer = NULL;
7781 rsurface.modelvertex3f_vertexbuffer = 0;
7782 rsurface.modelvertex3f_bufferoffset = 0;
7783 rsurface.modelsvector3f_vertexbuffer = 0;
7784 rsurface.modelsvector3f_bufferoffset = 0;
7785 rsurface.modeltvector3f_vertexbuffer = 0;
7786 rsurface.modeltvector3f_bufferoffset = 0;
7787 rsurface.modelnormal3f_vertexbuffer = 0;
7788 rsurface.modelnormal3f_bufferoffset = 0;
7789 rsurface.modelgeneratedvertex = true;
7793 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7794 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7795 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7796 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7797 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7799 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7800 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7802 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7803 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7804 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7805 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7806 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7807 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7808 rsurface.modelgeneratedvertex = false;
7810 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7811 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7812 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7813 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7814 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7815 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7816 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7817 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7818 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7819 rsurface.modelelement3i = model->surfmesh.data_element3i;
7820 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7821 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7822 rsurface.modelelement3s = model->surfmesh.data_element3s;
7823 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7824 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7825 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7826 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7827 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7828 rsurface.modelsurfaces = model->data_surfaces;
7829 rsurface.batchgeneratedvertex = false;
7830 rsurface.batchfirstvertex = 0;
7831 rsurface.batchnumvertices = 0;
7832 rsurface.batchfirsttriangle = 0;
7833 rsurface.batchnumtriangles = 0;
7834 rsurface.batchvertex3f = NULL;
7835 rsurface.batchvertex3f_vertexbuffer = NULL;
7836 rsurface.batchvertex3f_bufferoffset = 0;
7837 rsurface.batchsvector3f = NULL;
7838 rsurface.batchsvector3f_vertexbuffer = NULL;
7839 rsurface.batchsvector3f_bufferoffset = 0;
7840 rsurface.batchtvector3f = NULL;
7841 rsurface.batchtvector3f_vertexbuffer = NULL;
7842 rsurface.batchtvector3f_bufferoffset = 0;
7843 rsurface.batchnormal3f = NULL;
7844 rsurface.batchnormal3f_vertexbuffer = NULL;
7845 rsurface.batchnormal3f_bufferoffset = 0;
7846 rsurface.batchlightmapcolor4f = NULL;
7847 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7848 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7849 rsurface.batchtexcoordtexture2f = NULL;
7850 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7851 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7852 rsurface.batchtexcoordlightmap2f = NULL;
7853 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7854 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7855 rsurface.batchvertexmesh = NULL;
7856 rsurface.batchvertexmeshbuffer = NULL;
7857 rsurface.batchvertex3fbuffer = NULL;
7858 rsurface.batchelement3i = NULL;
7859 rsurface.batchelement3i_indexbuffer = NULL;
7860 rsurface.batchelement3i_bufferoffset = 0;
7861 rsurface.batchelement3s = NULL;
7862 rsurface.batchelement3s_indexbuffer = NULL;
7863 rsurface.batchelement3s_bufferoffset = 0;
7864 rsurface.passcolor4f = NULL;
7865 rsurface.passcolor4f_vertexbuffer = NULL;
7866 rsurface.passcolor4f_bufferoffset = 0;
7869 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)
7871 rsurface.entity = r_refdef.scene.worldentity;
7872 rsurface.skeleton = NULL;
7873 rsurface.ent_skinnum = 0;
7874 rsurface.ent_qwskin = -1;
7875 rsurface.ent_shadertime = shadertime;
7876 rsurface.ent_flags = entflags;
7877 rsurface.modelnumvertices = numvertices;
7878 rsurface.modelnumtriangles = numtriangles;
7879 rsurface.matrix = *matrix;
7880 rsurface.inversematrix = *inversematrix;
7881 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7882 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7883 R_EntityMatrix(&rsurface.matrix);
7884 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7885 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7886 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7887 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7888 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7889 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7890 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7891 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7892 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7893 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7894 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7895 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7896 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);
7897 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7898 rsurface.frameblend[0].lerp = 1;
7899 rsurface.ent_alttextures = false;
7900 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7901 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7904 rsurface.modelvertex3f = (float *)vertex3f;
7905 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7906 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7907 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7909 else if (wantnormals)
7911 rsurface.modelvertex3f = (float *)vertex3f;
7912 rsurface.modelsvector3f = NULL;
7913 rsurface.modeltvector3f = NULL;
7914 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7918 rsurface.modelvertex3f = (float *)vertex3f;
7919 rsurface.modelsvector3f = NULL;
7920 rsurface.modeltvector3f = NULL;
7921 rsurface.modelnormal3f = NULL;
7923 rsurface.modelvertexmesh = NULL;
7924 rsurface.modelvertexmeshbuffer = NULL;
7925 rsurface.modelvertex3fbuffer = NULL;
7926 rsurface.modelvertex3f_vertexbuffer = 0;
7927 rsurface.modelvertex3f_bufferoffset = 0;
7928 rsurface.modelsvector3f_vertexbuffer = 0;
7929 rsurface.modelsvector3f_bufferoffset = 0;
7930 rsurface.modeltvector3f_vertexbuffer = 0;
7931 rsurface.modeltvector3f_bufferoffset = 0;
7932 rsurface.modelnormal3f_vertexbuffer = 0;
7933 rsurface.modelnormal3f_bufferoffset = 0;
7934 rsurface.modelgeneratedvertex = true;
7935 rsurface.modellightmapcolor4f = (float *)color4f;
7936 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7937 rsurface.modellightmapcolor4f_bufferoffset = 0;
7938 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7939 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7940 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7941 rsurface.modeltexcoordlightmap2f = NULL;
7942 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7943 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7944 rsurface.modelelement3i = (int *)element3i;
7945 rsurface.modelelement3i_indexbuffer = NULL;
7946 rsurface.modelelement3i_bufferoffset = 0;
7947 rsurface.modelelement3s = (unsigned short *)element3s;
7948 rsurface.modelelement3s_indexbuffer = NULL;
7949 rsurface.modelelement3s_bufferoffset = 0;
7950 rsurface.modellightmapoffsets = NULL;
7951 rsurface.modelsurfaces = NULL;
7952 rsurface.batchgeneratedvertex = false;
7953 rsurface.batchfirstvertex = 0;
7954 rsurface.batchnumvertices = 0;
7955 rsurface.batchfirsttriangle = 0;
7956 rsurface.batchnumtriangles = 0;
7957 rsurface.batchvertex3f = NULL;
7958 rsurface.batchvertex3f_vertexbuffer = NULL;
7959 rsurface.batchvertex3f_bufferoffset = 0;
7960 rsurface.batchsvector3f = NULL;
7961 rsurface.batchsvector3f_vertexbuffer = NULL;
7962 rsurface.batchsvector3f_bufferoffset = 0;
7963 rsurface.batchtvector3f = NULL;
7964 rsurface.batchtvector3f_vertexbuffer = NULL;
7965 rsurface.batchtvector3f_bufferoffset = 0;
7966 rsurface.batchnormal3f = NULL;
7967 rsurface.batchnormal3f_vertexbuffer = NULL;
7968 rsurface.batchnormal3f_bufferoffset = 0;
7969 rsurface.batchlightmapcolor4f = NULL;
7970 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7971 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7972 rsurface.batchtexcoordtexture2f = NULL;
7973 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7974 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7975 rsurface.batchtexcoordlightmap2f = NULL;
7976 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7977 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7978 rsurface.batchvertexmesh = NULL;
7979 rsurface.batchvertexmeshbuffer = NULL;
7980 rsurface.batchvertex3fbuffer = NULL;
7981 rsurface.batchelement3i = NULL;
7982 rsurface.batchelement3i_indexbuffer = NULL;
7983 rsurface.batchelement3i_bufferoffset = 0;
7984 rsurface.batchelement3s = NULL;
7985 rsurface.batchelement3s_indexbuffer = NULL;
7986 rsurface.batchelement3s_bufferoffset = 0;
7987 rsurface.passcolor4f = NULL;
7988 rsurface.passcolor4f_vertexbuffer = NULL;
7989 rsurface.passcolor4f_bufferoffset = 0;
7991 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7993 if ((wantnormals || wanttangents) && !normal3f)
7995 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7996 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7998 if (wanttangents && !svector3f)
8000 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8001 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8002 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8007 float RSurf_FogPoint(const float *v)
8009 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8010 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8011 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8012 float FogHeightFade = r_refdef.fogheightfade;
8014 unsigned int fogmasktableindex;
8015 if (r_refdef.fogplaneviewabove)
8016 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8018 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8019 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8020 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8023 float RSurf_FogVertex(const float *v)
8025 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8026 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8027 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8028 float FogHeightFade = rsurface.fogheightfade;
8030 unsigned int fogmasktableindex;
8031 if (r_refdef.fogplaneviewabove)
8032 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8034 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8035 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8036 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8039 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8042 for (i = 0;i < numelements;i++)
8043 outelement3i[i] = inelement3i[i] + adjust;
8046 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8047 extern cvar_t gl_vbo;
8048 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8056 int surfacefirsttriangle;
8057 int surfacenumtriangles;
8058 int surfacefirstvertex;
8059 int surfaceendvertex;
8060 int surfacenumvertices;
8061 int batchnumvertices;
8062 int batchnumtriangles;
8066 qboolean dynamicvertex;
8070 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8072 q3shaderinfo_deform_t *deform;
8073 const msurface_t *surface, *firstsurface;
8074 r_vertexmesh_t *vertexmesh;
8075 if (!texturenumsurfaces)
8077 // find vertex range of this surface batch
8079 firstsurface = texturesurfacelist[0];
8080 firsttriangle = firstsurface->num_firsttriangle;
8081 batchnumvertices = 0;
8082 batchnumtriangles = 0;
8083 firstvertex = endvertex = firstsurface->num_firstvertex;
8084 for (i = 0;i < texturenumsurfaces;i++)
8086 surface = texturesurfacelist[i];
8087 if (surface != firstsurface + i)
8089 surfacefirstvertex = surface->num_firstvertex;
8090 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8091 surfacenumvertices = surface->num_vertices;
8092 surfacenumtriangles = surface->num_triangles;
8093 if (firstvertex > surfacefirstvertex)
8094 firstvertex = surfacefirstvertex;
8095 if (endvertex < surfaceendvertex)
8096 endvertex = surfaceendvertex;
8097 batchnumvertices += surfacenumvertices;
8098 batchnumtriangles += surfacenumtriangles;
8101 // we now know the vertex range used, and if there are any gaps in it
8102 rsurface.batchfirstvertex = firstvertex;
8103 rsurface.batchnumvertices = endvertex - firstvertex;
8104 rsurface.batchfirsttriangle = firsttriangle;
8105 rsurface.batchnumtriangles = batchnumtriangles;
8107 // this variable holds flags for which properties have been updated that
8108 // may require regenerating vertexmesh array...
8111 // check if any dynamic vertex processing must occur
8112 dynamicvertex = false;
8114 // if there is a chance of animated vertex colors, it's a dynamic batch
8115 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8117 dynamicvertex = true;
8118 batchneed |= BATCHNEED_NOGAPS;
8119 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8122 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8124 switch (deform->deform)
8127 case Q3DEFORM_PROJECTIONSHADOW:
8128 case Q3DEFORM_TEXT0:
8129 case Q3DEFORM_TEXT1:
8130 case Q3DEFORM_TEXT2:
8131 case Q3DEFORM_TEXT3:
8132 case Q3DEFORM_TEXT4:
8133 case Q3DEFORM_TEXT5:
8134 case Q3DEFORM_TEXT6:
8135 case Q3DEFORM_TEXT7:
8138 case Q3DEFORM_AUTOSPRITE:
8139 dynamicvertex = true;
8140 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8141 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8143 case Q3DEFORM_AUTOSPRITE2:
8144 dynamicvertex = true;
8145 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8146 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8148 case Q3DEFORM_NORMAL:
8149 dynamicvertex = true;
8150 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8151 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8154 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8155 break; // if wavefunc is a nop, ignore this transform
8156 dynamicvertex = true;
8157 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8158 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8160 case Q3DEFORM_BULGE:
8161 dynamicvertex = true;
8162 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8163 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8166 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8167 break; // if wavefunc is a nop, ignore this transform
8168 dynamicvertex = true;
8169 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8170 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8174 switch(rsurface.texture->tcgen.tcgen)
8177 case Q3TCGEN_TEXTURE:
8179 case Q3TCGEN_LIGHTMAP:
8180 dynamicvertex = true;
8181 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8182 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8184 case Q3TCGEN_VECTOR:
8185 dynamicvertex = true;
8186 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8187 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8189 case Q3TCGEN_ENVIRONMENT:
8190 dynamicvertex = true;
8191 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8192 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8195 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8197 dynamicvertex = true;
8198 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8199 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8202 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8204 dynamicvertex = true;
8205 batchneed |= BATCHNEED_NOGAPS;
8206 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8209 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8211 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8212 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8213 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8214 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8215 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8216 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8217 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8220 // when the model data has no vertex buffer (dynamic mesh), we need to
8222 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8223 batchneed |= BATCHNEED_NOGAPS;
8225 // if needsupdate, we have to do a dynamic vertex batch for sure
8226 if (needsupdate & batchneed)
8227 dynamicvertex = true;
8229 // see if we need to build vertexmesh from arrays
8230 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8231 dynamicvertex = true;
8233 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8234 // also some drivers strongly dislike firstvertex
8235 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8236 dynamicvertex = true;
8238 rsurface.batchvertex3f = rsurface.modelvertex3f;
8239 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8240 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8241 rsurface.batchsvector3f = rsurface.modelsvector3f;
8242 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8243 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8244 rsurface.batchtvector3f = rsurface.modeltvector3f;
8245 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8246 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8247 rsurface.batchnormal3f = rsurface.modelnormal3f;
8248 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8249 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8250 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8251 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8252 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8253 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8254 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8255 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8256 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8257 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8258 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8259 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8260 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8261 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8262 rsurface.batchelement3i = rsurface.modelelement3i;
8263 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8264 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8265 rsurface.batchelement3s = rsurface.modelelement3s;
8266 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8267 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8269 // if any dynamic vertex processing has to occur in software, we copy the
8270 // entire surface list together before processing to rebase the vertices
8271 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8273 // if any gaps exist and we do not have a static vertex buffer, we have to
8274 // copy the surface list together to avoid wasting upload bandwidth on the
8275 // vertices in the gaps.
8277 // if gaps exist and we have a static vertex buffer, we still have to
8278 // combine the index buffer ranges into one dynamic index buffer.
8280 // in all cases we end up with data that can be drawn in one call.
8284 // static vertex data, just set pointers...
8285 rsurface.batchgeneratedvertex = false;
8286 // if there are gaps, we want to build a combined index buffer,
8287 // otherwise use the original static buffer with an appropriate offset
8290 // build a new triangle elements array for this batch
8291 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8292 rsurface.batchfirsttriangle = 0;
8294 for (i = 0;i < texturenumsurfaces;i++)
8296 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8297 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8298 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8299 numtriangles += surfacenumtriangles;
8301 rsurface.batchelement3i_indexbuffer = NULL;
8302 rsurface.batchelement3i_bufferoffset = 0;
8303 rsurface.batchelement3s = NULL;
8304 rsurface.batchelement3s_indexbuffer = NULL;
8305 rsurface.batchelement3s_bufferoffset = 0;
8306 if (endvertex <= 65536)
8308 // make a 16bit (unsigned short) index array if possible
8309 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8310 for (i = 0;i < numtriangles*3;i++)
8311 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8317 // something needs software processing, do it for real...
8318 // we only directly handle separate array data in this case and then
8319 // generate interleaved data if needed...
8320 rsurface.batchgeneratedvertex = true;
8322 // now copy the vertex data into a combined array and make an index array
8323 // (this is what Quake3 does all the time)
8324 //if (gaps || rsurface.batchfirstvertex)
8326 rsurface.batchvertex3fbuffer = NULL;
8327 rsurface.batchvertexmesh = NULL;
8328 rsurface.batchvertexmeshbuffer = NULL;
8329 rsurface.batchvertex3f = NULL;
8330 rsurface.batchvertex3f_vertexbuffer = NULL;
8331 rsurface.batchvertex3f_bufferoffset = 0;
8332 rsurface.batchsvector3f = NULL;
8333 rsurface.batchsvector3f_vertexbuffer = NULL;
8334 rsurface.batchsvector3f_bufferoffset = 0;
8335 rsurface.batchtvector3f = NULL;
8336 rsurface.batchtvector3f_vertexbuffer = NULL;
8337 rsurface.batchtvector3f_bufferoffset = 0;
8338 rsurface.batchnormal3f = NULL;
8339 rsurface.batchnormal3f_vertexbuffer = NULL;
8340 rsurface.batchnormal3f_bufferoffset = 0;
8341 rsurface.batchlightmapcolor4f = NULL;
8342 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8343 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8344 rsurface.batchtexcoordtexture2f = NULL;
8345 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8346 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8347 rsurface.batchtexcoordlightmap2f = NULL;
8348 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8349 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8350 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8351 rsurface.batchelement3i_indexbuffer = NULL;
8352 rsurface.batchelement3i_bufferoffset = 0;
8353 rsurface.batchelement3s = NULL;
8354 rsurface.batchelement3s_indexbuffer = NULL;
8355 rsurface.batchelement3s_bufferoffset = 0;
8356 // we'll only be setting up certain arrays as needed
8357 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8358 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8359 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8360 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8361 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8362 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8363 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8365 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8366 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8368 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8369 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8370 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8371 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8372 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8373 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8376 for (i = 0;i < texturenumsurfaces;i++)
8378 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8379 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8380 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8381 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8382 // copy only the data requested
8383 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8384 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8385 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8387 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8388 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8389 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8390 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8391 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8393 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8394 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8396 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8397 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8398 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8399 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8400 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8401 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8403 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8404 numvertices += surfacenumvertices;
8405 numtriangles += surfacenumtriangles;
8408 // generate a 16bit index array as well if possible
8409 // (in general, dynamic batches fit)
8410 if (numvertices <= 65536)
8412 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8413 for (i = 0;i < numtriangles*3;i++)
8414 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8417 // since we've copied everything, the batch now starts at 0
8418 rsurface.batchfirstvertex = 0;
8419 rsurface.batchnumvertices = batchnumvertices;
8420 rsurface.batchfirsttriangle = 0;
8421 rsurface.batchnumtriangles = batchnumtriangles;
8424 // q1bsp surfaces rendered in vertex color mode have to have colors
8425 // calculated based on lightstyles
8426 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8428 // generate color arrays for the surfaces in this list
8433 const unsigned char *lm;
8434 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8435 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8436 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8438 for (i = 0;i < texturenumsurfaces;i++)
8440 surface = texturesurfacelist[i];
8441 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8442 surfacenumvertices = surface->num_vertices;
8443 if (surface->lightmapinfo->samples)
8445 for (j = 0;j < surfacenumvertices;j++)
8447 lm = surface->lightmapinfo->samples + offsets[j];
8448 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8449 VectorScale(lm, scale, c);
8450 if (surface->lightmapinfo->styles[1] != 255)
8452 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8454 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8455 VectorMA(c, scale, lm, c);
8456 if (surface->lightmapinfo->styles[2] != 255)
8459 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8460 VectorMA(c, scale, lm, c);
8461 if (surface->lightmapinfo->styles[3] != 255)
8464 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8465 VectorMA(c, scale, lm, c);
8472 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);
8478 for (j = 0;j < surfacenumvertices;j++)
8480 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8487 // if vertices are deformed (sprite flares and things in maps, possibly
8488 // water waves, bulges and other deformations), modify the copied vertices
8490 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8492 switch (deform->deform)
8495 case Q3DEFORM_PROJECTIONSHADOW:
8496 case Q3DEFORM_TEXT0:
8497 case Q3DEFORM_TEXT1:
8498 case Q3DEFORM_TEXT2:
8499 case Q3DEFORM_TEXT3:
8500 case Q3DEFORM_TEXT4:
8501 case Q3DEFORM_TEXT5:
8502 case Q3DEFORM_TEXT6:
8503 case Q3DEFORM_TEXT7:
8506 case Q3DEFORM_AUTOSPRITE:
8507 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8508 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8509 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8510 VectorNormalize(newforward);
8511 VectorNormalize(newright);
8512 VectorNormalize(newup);
8513 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8514 // rsurface.batchvertex3f_vertexbuffer = NULL;
8515 // rsurface.batchvertex3f_bufferoffset = 0;
8516 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8517 // rsurface.batchsvector3f_vertexbuffer = NULL;
8518 // rsurface.batchsvector3f_bufferoffset = 0;
8519 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8520 // rsurface.batchtvector3f_vertexbuffer = NULL;
8521 // rsurface.batchtvector3f_bufferoffset = 0;
8522 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8523 // rsurface.batchnormal3f_vertexbuffer = NULL;
8524 // rsurface.batchnormal3f_bufferoffset = 0;
8525 // a single autosprite surface can contain multiple sprites...
8526 for (j = 0;j < batchnumvertices - 3;j += 4)
8528 VectorClear(center);
8529 for (i = 0;i < 4;i++)
8530 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8531 VectorScale(center, 0.25f, center);
8532 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8533 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8534 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8535 for (i = 0;i < 4;i++)
8537 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8538 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8541 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8542 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8543 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);
8545 case Q3DEFORM_AUTOSPRITE2:
8546 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8547 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8548 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8549 VectorNormalize(newforward);
8550 VectorNormalize(newright);
8551 VectorNormalize(newup);
8552 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8553 // rsurface.batchvertex3f_vertexbuffer = NULL;
8554 // rsurface.batchvertex3f_bufferoffset = 0;
8556 const float *v1, *v2;
8566 memset(shortest, 0, sizeof(shortest));
8567 // a single autosprite surface can contain multiple sprites...
8568 for (j = 0;j < batchnumvertices - 3;j += 4)
8570 VectorClear(center);
8571 for (i = 0;i < 4;i++)
8572 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8573 VectorScale(center, 0.25f, center);
8574 // find the two shortest edges, then use them to define the
8575 // axis vectors for rotating around the central axis
8576 for (i = 0;i < 6;i++)
8578 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8579 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8580 l = VectorDistance2(v1, v2);
8581 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8583 l += (1.0f / 1024.0f);
8584 if (shortest[0].length2 > l || i == 0)
8586 shortest[1] = shortest[0];
8587 shortest[0].length2 = l;
8588 shortest[0].v1 = v1;
8589 shortest[0].v2 = v2;
8591 else if (shortest[1].length2 > l || i == 1)
8593 shortest[1].length2 = l;
8594 shortest[1].v1 = v1;
8595 shortest[1].v2 = v2;
8598 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8599 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8600 // this calculates the right vector from the shortest edge
8601 // and the up vector from the edge midpoints
8602 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8603 VectorNormalize(right);
8604 VectorSubtract(end, start, up);
8605 VectorNormalize(up);
8606 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8607 VectorSubtract(rsurface.localvieworigin, center, forward);
8608 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8609 VectorNegate(forward, forward);
8610 VectorReflect(forward, 0, up, forward);
8611 VectorNormalize(forward);
8612 CrossProduct(up, forward, newright);
8613 VectorNormalize(newright);
8614 // rotate the quad around the up axis vector, this is made
8615 // especially easy by the fact we know the quad is flat,
8616 // so we only have to subtract the center position and
8617 // measure distance along the right vector, and then
8618 // multiply that by the newright vector and add back the
8620 // we also need to subtract the old position to undo the
8621 // displacement from the center, which we do with a
8622 // DotProduct, the subtraction/addition of center is also
8623 // optimized into DotProducts here
8624 l = DotProduct(right, center);
8625 for (i = 0;i < 4;i++)
8627 v1 = rsurface.batchvertex3f + 3*(j+i);
8628 f = DotProduct(right, v1) - l;
8629 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8633 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8635 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8636 // rsurface.batchnormal3f_vertexbuffer = NULL;
8637 // rsurface.batchnormal3f_bufferoffset = 0;
8638 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8640 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8642 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8643 // rsurface.batchsvector3f_vertexbuffer = NULL;
8644 // rsurface.batchsvector3f_bufferoffset = 0;
8645 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8646 // rsurface.batchtvector3f_vertexbuffer = NULL;
8647 // rsurface.batchtvector3f_bufferoffset = 0;
8648 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);
8651 case Q3DEFORM_NORMAL:
8652 // deform the normals to make reflections wavey
8653 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8654 rsurface.batchnormal3f_vertexbuffer = NULL;
8655 rsurface.batchnormal3f_bufferoffset = 0;
8656 for (j = 0;j < batchnumvertices;j++)
8659 float *normal = rsurface.batchnormal3f + 3*j;
8660 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8661 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8662 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]);
8663 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]);
8664 VectorNormalize(normal);
8666 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8668 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8669 // rsurface.batchsvector3f_vertexbuffer = NULL;
8670 // rsurface.batchsvector3f_bufferoffset = 0;
8671 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8672 // rsurface.batchtvector3f_vertexbuffer = NULL;
8673 // rsurface.batchtvector3f_bufferoffset = 0;
8674 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);
8678 // deform vertex array to make wavey water and flags and such
8679 waveparms[0] = deform->waveparms[0];
8680 waveparms[1] = deform->waveparms[1];
8681 waveparms[2] = deform->waveparms[2];
8682 waveparms[3] = deform->waveparms[3];
8683 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8684 break; // if wavefunc is a nop, don't make a dynamic vertex array
8685 // this is how a divisor of vertex influence on deformation
8686 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8687 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8688 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8689 // rsurface.batchvertex3f_vertexbuffer = NULL;
8690 // rsurface.batchvertex3f_bufferoffset = 0;
8691 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8692 // rsurface.batchnormal3f_vertexbuffer = NULL;
8693 // rsurface.batchnormal3f_bufferoffset = 0;
8694 for (j = 0;j < batchnumvertices;j++)
8696 // if the wavefunc depends on time, evaluate it per-vertex
8699 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8700 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8702 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8704 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8705 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8706 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8708 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8709 // rsurface.batchsvector3f_vertexbuffer = NULL;
8710 // rsurface.batchsvector3f_bufferoffset = 0;
8711 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8712 // rsurface.batchtvector3f_vertexbuffer = NULL;
8713 // rsurface.batchtvector3f_bufferoffset = 0;
8714 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);
8717 case Q3DEFORM_BULGE:
8718 // deform vertex array to make the surface have moving bulges
8719 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8720 // rsurface.batchvertex3f_vertexbuffer = NULL;
8721 // rsurface.batchvertex3f_bufferoffset = 0;
8722 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8723 // rsurface.batchnormal3f_vertexbuffer = NULL;
8724 // rsurface.batchnormal3f_bufferoffset = 0;
8725 for (j = 0;j < batchnumvertices;j++)
8727 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8728 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8730 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8731 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8732 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8734 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8735 // rsurface.batchsvector3f_vertexbuffer = NULL;
8736 // rsurface.batchsvector3f_bufferoffset = 0;
8737 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8738 // rsurface.batchtvector3f_vertexbuffer = NULL;
8739 // rsurface.batchtvector3f_bufferoffset = 0;
8740 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);
8744 // deform vertex array
8745 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8746 break; // if wavefunc is a nop, don't make a dynamic vertex array
8747 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8748 VectorScale(deform->parms, scale, waveparms);
8749 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8750 // rsurface.batchvertex3f_vertexbuffer = NULL;
8751 // rsurface.batchvertex3f_bufferoffset = 0;
8752 for (j = 0;j < batchnumvertices;j++)
8753 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8758 // generate texcoords based on the chosen texcoord source
8759 switch(rsurface.texture->tcgen.tcgen)
8762 case Q3TCGEN_TEXTURE:
8764 case Q3TCGEN_LIGHTMAP:
8765 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8766 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8767 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8768 if (rsurface.batchtexcoordlightmap2f)
8769 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8771 case Q3TCGEN_VECTOR:
8772 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8773 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8774 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8775 for (j = 0;j < batchnumvertices;j++)
8777 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8778 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8781 case Q3TCGEN_ENVIRONMENT:
8782 // make environment reflections using a spheremap
8783 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8784 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8785 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8786 for (j = 0;j < batchnumvertices;j++)
8788 // identical to Q3A's method, but executed in worldspace so
8789 // carried models can be shiny too
8791 float viewer[3], d, reflected[3], worldreflected[3];
8793 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8794 // VectorNormalize(viewer);
8796 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8798 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8799 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8800 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8801 // note: this is proportinal to viewer, so we can normalize later
8803 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8804 VectorNormalize(worldreflected);
8806 // note: this sphere map only uses world x and z!
8807 // so positive and negative y will LOOK THE SAME.
8808 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8809 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8813 // the only tcmod that needs software vertex processing is turbulent, so
8814 // check for it here and apply the changes if needed
8815 // and we only support that as the first one
8816 // (handling a mixture of turbulent and other tcmods would be problematic
8817 // without punting it entirely to a software path)
8818 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8820 amplitude = rsurface.texture->tcmods[0].parms[1];
8821 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8822 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8823 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8824 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8825 for (j = 0;j < batchnumvertices;j++)
8827 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);
8828 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8832 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8834 // convert the modified arrays to vertex structs
8835 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8836 // rsurface.batchvertexmeshbuffer = NULL;
8837 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8838 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8839 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8840 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8841 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8842 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8843 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8845 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8847 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8848 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8851 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8852 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8853 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8854 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8855 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8856 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8857 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8858 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8859 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8863 void RSurf_DrawBatch(void)
8865 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8866 // through the pipeline, killing it earlier in the pipeline would have
8867 // per-surface overhead rather than per-batch overhead, so it's best to
8868 // reject it here, before it hits glDraw.
8869 if (rsurface.batchnumtriangles == 0)
8872 // batch debugging code
8873 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8879 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8880 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8883 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8885 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8887 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8888 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);
8895 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);
8898 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8900 // pick the closest matching water plane
8901 int planeindex, vertexindex, bestplaneindex = -1;
8905 r_waterstate_waterplane_t *p;
8906 qboolean prepared = false;
8908 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8910 if(p->camera_entity != rsurface.texture->camera_entity)
8915 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8917 if(rsurface.batchnumvertices == 0)
8920 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8922 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8923 d += fabs(PlaneDiff(vert, &p->plane));
8925 if (bestd > d || bestplaneindex < 0)
8928 bestplaneindex = planeindex;
8931 return bestplaneindex;
8932 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8933 // this situation though, as it might be better to render single larger
8934 // batches with useless stuff (backface culled for example) than to
8935 // render multiple smaller batches
8938 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8941 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8942 rsurface.passcolor4f_vertexbuffer = 0;
8943 rsurface.passcolor4f_bufferoffset = 0;
8944 for (i = 0;i < rsurface.batchnumvertices;i++)
8945 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8948 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8955 if (rsurface.passcolor4f)
8957 // generate color arrays
8958 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8959 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8960 rsurface.passcolor4f_vertexbuffer = 0;
8961 rsurface.passcolor4f_bufferoffset = 0;
8962 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)
8964 f = RSurf_FogVertex(v);
8973 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8974 rsurface.passcolor4f_vertexbuffer = 0;
8975 rsurface.passcolor4f_bufferoffset = 0;
8976 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8978 f = RSurf_FogVertex(v);
8987 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8994 if (!rsurface.passcolor4f)
8996 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8997 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8998 rsurface.passcolor4f_vertexbuffer = 0;
8999 rsurface.passcolor4f_bufferoffset = 0;
9000 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)
9002 f = RSurf_FogVertex(v);
9003 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9004 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9005 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9010 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9015 if (!rsurface.passcolor4f)
9017 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9018 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9019 rsurface.passcolor4f_vertexbuffer = 0;
9020 rsurface.passcolor4f_bufferoffset = 0;
9021 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9030 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9035 if (!rsurface.passcolor4f)
9037 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9038 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9039 rsurface.passcolor4f_vertexbuffer = 0;
9040 rsurface.passcolor4f_bufferoffset = 0;
9041 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9043 c2[0] = c[0] + r_refdef.scene.ambient;
9044 c2[1] = c[1] + r_refdef.scene.ambient;
9045 c2[2] = c[2] + r_refdef.scene.ambient;
9050 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9053 rsurface.passcolor4f = NULL;
9054 rsurface.passcolor4f_vertexbuffer = 0;
9055 rsurface.passcolor4f_bufferoffset = 0;
9056 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9057 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9058 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9059 GL_Color(r, g, b, a);
9060 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9064 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9066 // TODO: optimize applyfog && applycolor case
9067 // just apply fog if necessary, and tint the fog color array if necessary
9068 rsurface.passcolor4f = NULL;
9069 rsurface.passcolor4f_vertexbuffer = 0;
9070 rsurface.passcolor4f_bufferoffset = 0;
9071 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9072 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9073 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9074 GL_Color(r, g, b, a);
9078 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9081 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9082 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9083 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9084 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9085 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9086 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9087 GL_Color(r, g, b, a);
9091 static void RSurf_DrawBatch_GL11_ClampColor(void)
9096 if (!rsurface.passcolor4f)
9098 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9100 c2[0] = bound(0.0f, c1[0], 1.0f);
9101 c2[1] = bound(0.0f, c1[1], 1.0f);
9102 c2[2] = bound(0.0f, c1[2], 1.0f);
9103 c2[3] = bound(0.0f, c1[3], 1.0f);
9107 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9117 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9118 rsurface.passcolor4f_vertexbuffer = 0;
9119 rsurface.passcolor4f_bufferoffset = 0;
9120 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)
9122 f = -DotProduct(r_refdef.view.forward, n);
9124 f = f * 0.85 + 0.15; // work around so stuff won't get black
9125 f *= r_refdef.lightmapintensity;
9126 Vector4Set(c, f, f, f, 1);
9130 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9132 RSurf_DrawBatch_GL11_ApplyFakeLight();
9133 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9134 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9135 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9136 GL_Color(r, g, b, a);
9140 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9148 vec3_t ambientcolor;
9149 vec3_t diffusecolor;
9153 VectorCopy(rsurface.modellight_lightdir, lightdir);
9154 f = 0.5f * r_refdef.lightmapintensity;
9155 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9156 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9157 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9158 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9159 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9160 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9162 if (VectorLength2(diffusecolor) > 0)
9164 // q3-style directional shading
9165 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9166 rsurface.passcolor4f_vertexbuffer = 0;
9167 rsurface.passcolor4f_bufferoffset = 0;
9168 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)
9170 if ((f = DotProduct(n, lightdir)) > 0)
9171 VectorMA(ambientcolor, f, diffusecolor, c);
9173 VectorCopy(ambientcolor, c);
9180 *applycolor = false;
9184 *r = ambientcolor[0];
9185 *g = ambientcolor[1];
9186 *b = ambientcolor[2];
9187 rsurface.passcolor4f = NULL;
9188 rsurface.passcolor4f_vertexbuffer = 0;
9189 rsurface.passcolor4f_bufferoffset = 0;
9193 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9195 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9196 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9197 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9198 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9199 GL_Color(r, g, b, a);
9203 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9209 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9211 f = 1 - RSurf_FogVertex(v);
9219 void RSurf_SetupDepthAndCulling(void)
9221 // submodels are biased to avoid z-fighting with world surfaces that they
9222 // may be exactly overlapping (avoids z-fighting artifacts on certain
9223 // doors and things in Quake maps)
9224 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9225 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9226 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9227 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9230 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9232 // transparent sky would be ridiculous
9233 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9235 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9236 skyrenderlater = true;
9237 RSurf_SetupDepthAndCulling();
9239 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9240 // skymasking on them, and Quake3 never did sky masking (unlike
9241 // software Quake and software Quake2), so disable the sky masking
9242 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9243 // and skymasking also looks very bad when noclipping outside the
9244 // level, so don't use it then either.
9245 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9247 R_Mesh_ResetTextureState();
9248 if (skyrendermasked)
9250 R_SetupShader_DepthOrShadow();
9251 // depth-only (masking)
9252 GL_ColorMask(0,0,0,0);
9253 // just to make sure that braindead drivers don't draw
9254 // anything despite that colormask...
9255 GL_BlendFunc(GL_ZERO, GL_ONE);
9256 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9257 if (rsurface.batchvertex3fbuffer)
9258 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9260 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9264 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9266 GL_BlendFunc(GL_ONE, GL_ZERO);
9267 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9268 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9269 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9272 if (skyrendermasked)
9273 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9275 R_Mesh_ResetTextureState();
9276 GL_Color(1, 1, 1, 1);
9279 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9280 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9281 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9283 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9287 // render screenspace normalmap to texture
9289 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9294 // bind lightmap texture
9296 // water/refraction/reflection/camera surfaces have to be handled specially
9297 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9299 int start, end, startplaneindex;
9300 for (start = 0;start < texturenumsurfaces;start = end)
9302 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9303 if(startplaneindex < 0)
9305 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9306 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9310 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9312 // now that we have a batch using the same planeindex, render it
9313 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9315 // render water or distortion background
9317 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));
9319 // blend surface on top
9320 GL_DepthMask(false);
9321 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9324 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9326 // render surface with reflection texture as input
9327 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9328 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9335 // render surface batch normally
9336 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9337 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9341 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9343 // OpenGL 1.3 path - anything not completely ancient
9344 qboolean applycolor;
9347 const texturelayer_t *layer;
9348 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);
9349 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9351 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9354 int layertexrgbscale;
9355 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9357 if (layerindex == 0)
9361 GL_AlphaTest(false);
9362 GL_DepthFunc(GL_EQUAL);
9365 GL_DepthMask(layer->depthmask && writedepth);
9366 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9367 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9369 layertexrgbscale = 4;
9370 VectorScale(layer->color, 0.25f, layercolor);
9372 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9374 layertexrgbscale = 2;
9375 VectorScale(layer->color, 0.5f, layercolor);
9379 layertexrgbscale = 1;
9380 VectorScale(layer->color, 1.0f, layercolor);
9382 layercolor[3] = layer->color[3];
9383 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9384 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9385 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9386 switch (layer->type)
9388 case TEXTURELAYERTYPE_LITTEXTURE:
9389 // single-pass lightmapped texture with 2x rgbscale
9390 R_Mesh_TexBind(0, r_texture_white);
9391 R_Mesh_TexMatrix(0, NULL);
9392 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9393 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9394 R_Mesh_TexBind(1, layer->texture);
9395 R_Mesh_TexMatrix(1, &layer->texmatrix);
9396 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9397 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9398 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9399 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9400 else if (FAKELIGHT_ENABLED)
9401 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9402 else if (rsurface.uselightmaptexture)
9403 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9405 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9407 case TEXTURELAYERTYPE_TEXTURE:
9408 // singletexture unlit texture with transparency support
9409 R_Mesh_TexBind(0, layer->texture);
9410 R_Mesh_TexMatrix(0, &layer->texmatrix);
9411 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9412 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9413 R_Mesh_TexBind(1, 0);
9414 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9415 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9417 case TEXTURELAYERTYPE_FOG:
9418 // singletexture fogging
9421 R_Mesh_TexBind(0, layer->texture);
9422 R_Mesh_TexMatrix(0, &layer->texmatrix);
9423 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9424 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9428 R_Mesh_TexBind(0, 0);
9429 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9431 R_Mesh_TexBind(1, 0);
9432 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9433 // generate a color array for the fog pass
9434 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9435 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9439 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9442 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9444 GL_DepthFunc(GL_LEQUAL);
9445 GL_AlphaTest(false);
9449 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9451 // OpenGL 1.1 - crusty old voodoo path
9454 const texturelayer_t *layer;
9455 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);
9456 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9458 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9462 if (layerindex == 0)
9466 GL_AlphaTest(false);
9467 GL_DepthFunc(GL_EQUAL);
9470 GL_DepthMask(layer->depthmask && writedepth);
9471 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9472 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9473 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9474 switch (layer->type)
9476 case TEXTURELAYERTYPE_LITTEXTURE:
9477 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9479 // two-pass lit texture with 2x rgbscale
9480 // first the lightmap pass
9481 R_Mesh_TexBind(0, r_texture_white);
9482 R_Mesh_TexMatrix(0, NULL);
9483 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9484 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9485 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9486 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9487 else if (FAKELIGHT_ENABLED)
9488 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9489 else if (rsurface.uselightmaptexture)
9490 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9492 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9493 // then apply the texture to it
9494 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9495 R_Mesh_TexBind(0, layer->texture);
9496 R_Mesh_TexMatrix(0, &layer->texmatrix);
9497 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9498 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9499 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);
9503 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9504 R_Mesh_TexBind(0, layer->texture);
9505 R_Mesh_TexMatrix(0, &layer->texmatrix);
9506 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9507 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9508 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9509 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);
9511 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);
9514 case TEXTURELAYERTYPE_TEXTURE:
9515 // singletexture unlit texture with transparency support
9516 R_Mesh_TexBind(0, layer->texture);
9517 R_Mesh_TexMatrix(0, &layer->texmatrix);
9518 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9519 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9520 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);
9522 case TEXTURELAYERTYPE_FOG:
9523 // singletexture fogging
9526 R_Mesh_TexBind(0, layer->texture);
9527 R_Mesh_TexMatrix(0, &layer->texmatrix);
9528 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9529 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9533 R_Mesh_TexBind(0, 0);
9534 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9536 // generate a color array for the fog pass
9537 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9538 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9542 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9545 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9547 GL_DepthFunc(GL_LEQUAL);
9548 GL_AlphaTest(false);
9552 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9556 r_vertexgeneric_t *batchvertex;
9559 // R_Mesh_ResetTextureState();
9560 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9562 if(rsurface.texture && rsurface.texture->currentskinframe)
9564 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9565 c[3] *= rsurface.texture->currentalpha;
9575 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9577 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9578 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9579 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9582 // brighten it up (as texture value 127 means "unlit")
9583 c[0] *= 2 * r_refdef.view.colorscale;
9584 c[1] *= 2 * r_refdef.view.colorscale;
9585 c[2] *= 2 * r_refdef.view.colorscale;
9587 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9588 c[3] *= r_wateralpha.value;
9590 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9592 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9593 GL_DepthMask(false);
9595 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9597 GL_BlendFunc(GL_ONE, GL_ONE);
9598 GL_DepthMask(false);
9600 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9602 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9603 GL_DepthMask(false);
9605 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9607 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9608 GL_DepthMask(false);
9612 GL_BlendFunc(GL_ONE, GL_ZERO);
9613 GL_DepthMask(writedepth);
9616 if (r_showsurfaces.integer == 3)
9618 rsurface.passcolor4f = NULL;
9620 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9622 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9624 rsurface.passcolor4f = NULL;
9625 rsurface.passcolor4f_vertexbuffer = 0;
9626 rsurface.passcolor4f_bufferoffset = 0;
9628 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9630 qboolean applycolor = true;
9633 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9635 r_refdef.lightmapintensity = 1;
9636 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9637 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9639 else if (FAKELIGHT_ENABLED)
9641 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9643 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9644 RSurf_DrawBatch_GL11_ApplyFakeLight();
9645 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9649 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9651 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9652 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9653 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9656 if(!rsurface.passcolor4f)
9657 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9659 RSurf_DrawBatch_GL11_ApplyAmbient();
9660 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9661 if(r_refdef.fogenabled)
9662 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9663 RSurf_DrawBatch_GL11_ClampColor();
9665 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9666 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9669 else if (!r_refdef.view.showdebug)
9671 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9672 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9673 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9675 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9676 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9678 R_Mesh_PrepareVertices_Generic_Unlock();
9681 else if (r_showsurfaces.integer == 4)
9683 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9684 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9685 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9687 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9688 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9689 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9691 R_Mesh_PrepareVertices_Generic_Unlock();
9694 else if (r_showsurfaces.integer == 2)
9697 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9698 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9699 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9701 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9702 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9703 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9704 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9705 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9706 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9707 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9709 R_Mesh_PrepareVertices_Generic_Unlock();
9710 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9714 int texturesurfaceindex;
9716 const msurface_t *surface;
9717 float surfacecolor4f[4];
9718 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9719 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9721 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9723 surface = texturesurfacelist[texturesurfaceindex];
9724 k = (int)(((size_t)surface) / sizeof(msurface_t));
9725 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9726 for (j = 0;j < surface->num_vertices;j++)
9728 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9729 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9733 R_Mesh_PrepareVertices_Generic_Unlock();
9738 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9741 RSurf_SetupDepthAndCulling();
9742 if (r_showsurfaces.integer)
9744 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9747 switch (vid.renderpath)
9749 case RENDERPATH_GL20:
9750 case RENDERPATH_D3D9:
9751 case RENDERPATH_D3D10:
9752 case RENDERPATH_D3D11:
9753 case RENDERPATH_SOFT:
9754 case RENDERPATH_GLES2:
9755 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9757 case RENDERPATH_GL13:
9758 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9760 case RENDERPATH_GL11:
9761 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9767 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9770 RSurf_SetupDepthAndCulling();
9771 if (r_showsurfaces.integer)
9773 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9776 switch (vid.renderpath)
9778 case RENDERPATH_GL20:
9779 case RENDERPATH_D3D9:
9780 case RENDERPATH_D3D10:
9781 case RENDERPATH_D3D11:
9782 case RENDERPATH_SOFT:
9783 case RENDERPATH_GLES2:
9784 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9786 case RENDERPATH_GL13:
9787 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9789 case RENDERPATH_GL11:
9790 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9796 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9799 int texturenumsurfaces, endsurface;
9801 const msurface_t *surface;
9802 #define MAXBATCH_TRANSPARENTSURFACES 256
9803 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9805 // if the model is static it doesn't matter what value we give for
9806 // wantnormals and wanttangents, so this logic uses only rules applicable
9807 // to a model, knowing that they are meaningless otherwise
9808 if (ent == r_refdef.scene.worldentity)
9809 RSurf_ActiveWorldEntity();
9810 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9811 RSurf_ActiveModelEntity(ent, false, false, false);
9814 switch (vid.renderpath)
9816 case RENDERPATH_GL20:
9817 case RENDERPATH_D3D9:
9818 case RENDERPATH_D3D10:
9819 case RENDERPATH_D3D11:
9820 case RENDERPATH_SOFT:
9821 case RENDERPATH_GLES2:
9822 RSurf_ActiveModelEntity(ent, true, true, false);
9824 case RENDERPATH_GL13:
9825 case RENDERPATH_GL11:
9826 RSurf_ActiveModelEntity(ent, true, false, false);
9831 if (r_transparentdepthmasking.integer)
9833 qboolean setup = false;
9834 for (i = 0;i < numsurfaces;i = j)
9837 surface = rsurface.modelsurfaces + surfacelist[i];
9838 texture = surface->texture;
9839 rsurface.texture = R_GetCurrentTexture(texture);
9840 rsurface.lightmaptexture = NULL;
9841 rsurface.deluxemaptexture = NULL;
9842 rsurface.uselightmaptexture = false;
9843 // scan ahead until we find a different texture
9844 endsurface = min(i + 1024, numsurfaces);
9845 texturenumsurfaces = 0;
9846 texturesurfacelist[texturenumsurfaces++] = surface;
9847 for (;j < endsurface;j++)
9849 surface = rsurface.modelsurfaces + surfacelist[j];
9850 if (texture != surface->texture)
9852 texturesurfacelist[texturenumsurfaces++] = surface;
9854 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9856 // render the range of surfaces as depth
9860 GL_ColorMask(0,0,0,0);
9863 GL_BlendFunc(GL_ONE, GL_ZERO);
9865 // R_Mesh_ResetTextureState();
9866 R_SetupShader_DepthOrShadow();
9868 RSurf_SetupDepthAndCulling();
9869 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9870 if (rsurface.batchvertex3fbuffer)
9871 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9873 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9877 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9880 for (i = 0;i < numsurfaces;i = j)
9883 surface = rsurface.modelsurfaces + surfacelist[i];
9884 texture = surface->texture;
9885 rsurface.texture = R_GetCurrentTexture(texture);
9886 // scan ahead until we find a different texture
9887 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9888 texturenumsurfaces = 0;
9889 texturesurfacelist[texturenumsurfaces++] = surface;
9890 if(FAKELIGHT_ENABLED)
9892 rsurface.lightmaptexture = NULL;
9893 rsurface.deluxemaptexture = NULL;
9894 rsurface.uselightmaptexture = false;
9895 for (;j < endsurface;j++)
9897 surface = rsurface.modelsurfaces + surfacelist[j];
9898 if (texture != surface->texture)
9900 texturesurfacelist[texturenumsurfaces++] = surface;
9905 rsurface.lightmaptexture = surface->lightmaptexture;
9906 rsurface.deluxemaptexture = surface->deluxemaptexture;
9907 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9908 for (;j < endsurface;j++)
9910 surface = rsurface.modelsurfaces + surfacelist[j];
9911 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9913 texturesurfacelist[texturenumsurfaces++] = surface;
9916 // render the range of surfaces
9917 if (ent == r_refdef.scene.worldentity)
9918 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9920 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9922 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9925 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9927 // transparent surfaces get pushed off into the transparent queue
9928 int surfacelistindex;
9929 const msurface_t *surface;
9930 vec3_t tempcenter, center;
9931 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9933 surface = texturesurfacelist[surfacelistindex];
9934 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9935 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9936 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9937 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9938 if (queueentity->transparent_offset) // transparent offset
9940 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9941 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9942 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9944 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9948 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9950 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9952 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9954 RSurf_SetupDepthAndCulling();
9955 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9956 if (rsurface.batchvertex3fbuffer)
9957 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9959 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9963 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9965 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9968 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9971 if (!rsurface.texture->currentnumlayers)
9973 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9974 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9976 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9978 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9979 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9980 else if (!rsurface.texture->currentnumlayers)
9982 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9984 // in the deferred case, transparent surfaces were queued during prepass
9985 if (!r_shadow_usingdeferredprepass)
9986 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9990 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9991 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9996 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10000 R_FrameData_SetMark();
10001 // break the surface list down into batches by texture and use of lightmapping
10002 for (i = 0;i < numsurfaces;i = j)
10005 // texture is the base texture pointer, rsurface.texture is the
10006 // current frame/skin the texture is directing us to use (for example
10007 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10008 // use skin 1 instead)
10009 texture = surfacelist[i]->texture;
10010 rsurface.texture = R_GetCurrentTexture(texture);
10011 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10013 // if this texture is not the kind we want, skip ahead to the next one
10014 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10018 if(FAKELIGHT_ENABLED || depthonly || prepass)
10020 rsurface.lightmaptexture = NULL;
10021 rsurface.deluxemaptexture = NULL;
10022 rsurface.uselightmaptexture = false;
10023 // simply scan ahead until we find a different texture or lightmap state
10024 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10029 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10030 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10031 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10032 // simply scan ahead until we find a different texture or lightmap state
10033 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10036 // render the range of surfaces
10037 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10039 R_FrameData_ReturnToMark();
10042 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10046 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10049 if (!rsurface.texture->currentnumlayers)
10051 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10052 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10054 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10056 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10057 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10058 else if (!rsurface.texture->currentnumlayers)
10060 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10062 // in the deferred case, transparent surfaces were queued during prepass
10063 if (!r_shadow_usingdeferredprepass)
10064 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10068 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10069 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10074 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10077 texture_t *texture;
10078 R_FrameData_SetMark();
10079 // break the surface list down into batches by texture and use of lightmapping
10080 for (i = 0;i < numsurfaces;i = j)
10083 // texture is the base texture pointer, rsurface.texture is the
10084 // current frame/skin the texture is directing us to use (for example
10085 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10086 // use skin 1 instead)
10087 texture = surfacelist[i]->texture;
10088 rsurface.texture = R_GetCurrentTexture(texture);
10089 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10091 // if this texture is not the kind we want, skip ahead to the next one
10092 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10096 if(FAKELIGHT_ENABLED || depthonly || prepass)
10098 rsurface.lightmaptexture = NULL;
10099 rsurface.deluxemaptexture = NULL;
10100 rsurface.uselightmaptexture = false;
10101 // simply scan ahead until we find a different texture or lightmap state
10102 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10107 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10108 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10109 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10110 // simply scan ahead until we find a different texture or lightmap state
10111 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10114 // render the range of surfaces
10115 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10117 R_FrameData_ReturnToMark();
10120 float locboxvertex3f[6*4*3] =
10122 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10123 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10124 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10125 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10126 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10127 1,0,0, 0,0,0, 0,1,0, 1,1,0
10130 unsigned short locboxelements[6*2*3] =
10135 12,13,14, 12,14,15,
10136 16,17,18, 16,18,19,
10140 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10143 cl_locnode_t *loc = (cl_locnode_t *)ent;
10145 float vertex3f[6*4*3];
10147 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10148 GL_DepthMask(false);
10149 GL_DepthRange(0, 1);
10150 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10151 GL_DepthTest(true);
10152 GL_CullFace(GL_NONE);
10153 R_EntityMatrix(&identitymatrix);
10155 // R_Mesh_ResetTextureState();
10157 i = surfacelist[0];
10158 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10159 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10160 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10161 surfacelist[0] < 0 ? 0.5f : 0.125f);
10163 if (VectorCompare(loc->mins, loc->maxs))
10165 VectorSet(size, 2, 2, 2);
10166 VectorMA(loc->mins, -0.5f, size, mins);
10170 VectorCopy(loc->mins, mins);
10171 VectorSubtract(loc->maxs, loc->mins, size);
10174 for (i = 0;i < 6*4*3;)
10175 for (j = 0;j < 3;j++, i++)
10176 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10178 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10179 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10180 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10183 void R_DrawLocs(void)
10186 cl_locnode_t *loc, *nearestloc;
10188 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10189 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10191 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10192 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10196 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10198 if (decalsystem->decals)
10199 Mem_Free(decalsystem->decals);
10200 memset(decalsystem, 0, sizeof(*decalsystem));
10203 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)
10206 tridecal_t *decals;
10209 // expand or initialize the system
10210 if (decalsystem->maxdecals <= decalsystem->numdecals)
10212 decalsystem_t old = *decalsystem;
10213 qboolean useshortelements;
10214 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10215 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10216 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)));
10217 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10218 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10219 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10220 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10221 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10222 if (decalsystem->numdecals)
10223 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10225 Mem_Free(old.decals);
10226 for (i = 0;i < decalsystem->maxdecals*3;i++)
10227 decalsystem->element3i[i] = i;
10228 if (useshortelements)
10229 for (i = 0;i < decalsystem->maxdecals*3;i++)
10230 decalsystem->element3s[i] = i;
10233 // grab a decal and search for another free slot for the next one
10234 decals = decalsystem->decals;
10235 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10236 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10238 decalsystem->freedecal = i;
10239 if (decalsystem->numdecals <= i)
10240 decalsystem->numdecals = i + 1;
10242 // initialize the decal
10244 decal->triangleindex = triangleindex;
10245 decal->surfaceindex = surfaceindex;
10246 decal->decalsequence = decalsequence;
10247 decal->color4f[0][0] = c0[0];
10248 decal->color4f[0][1] = c0[1];
10249 decal->color4f[0][2] = c0[2];
10250 decal->color4f[0][3] = 1;
10251 decal->color4f[1][0] = c1[0];
10252 decal->color4f[1][1] = c1[1];
10253 decal->color4f[1][2] = c1[2];
10254 decal->color4f[1][3] = 1;
10255 decal->color4f[2][0] = c2[0];
10256 decal->color4f[2][1] = c2[1];
10257 decal->color4f[2][2] = c2[2];
10258 decal->color4f[2][3] = 1;
10259 decal->vertex3f[0][0] = v0[0];
10260 decal->vertex3f[0][1] = v0[1];
10261 decal->vertex3f[0][2] = v0[2];
10262 decal->vertex3f[1][0] = v1[0];
10263 decal->vertex3f[1][1] = v1[1];
10264 decal->vertex3f[1][2] = v1[2];
10265 decal->vertex3f[2][0] = v2[0];
10266 decal->vertex3f[2][1] = v2[1];
10267 decal->vertex3f[2][2] = v2[2];
10268 decal->texcoord2f[0][0] = t0[0];
10269 decal->texcoord2f[0][1] = t0[1];
10270 decal->texcoord2f[1][0] = t1[0];
10271 decal->texcoord2f[1][1] = t1[1];
10272 decal->texcoord2f[2][0] = t2[0];
10273 decal->texcoord2f[2][1] = t2[1];
10276 extern cvar_t cl_decals_bias;
10277 extern cvar_t cl_decals_models;
10278 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10279 // baseparms, parms, temps
10280 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)
10285 const float *vertex3f;
10286 const float *normal3f;
10288 float points[2][9][3];
10295 e = rsurface.modelelement3i + 3*triangleindex;
10297 vertex3f = rsurface.modelvertex3f;
10298 normal3f = rsurface.modelnormal3f;
10302 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10304 index = 3*e[cornerindex];
10305 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10310 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10312 index = 3*e[cornerindex];
10313 VectorCopy(vertex3f + index, v[cornerindex]);
10318 //TriangleNormal(v[0], v[1], v[2], normal);
10319 //if (DotProduct(normal, localnormal) < 0.0f)
10321 // clip by each of the box planes formed from the projection matrix
10322 // if anything survives, we emit the decal
10323 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]);
10326 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]);
10329 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]);
10332 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]);
10335 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]);
10338 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]);
10341 // some part of the triangle survived, so we have to accept it...
10344 // dynamic always uses the original triangle
10346 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10348 index = 3*e[cornerindex];
10349 VectorCopy(vertex3f + index, v[cornerindex]);
10352 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10354 // convert vertex positions to texcoords
10355 Matrix4x4_Transform(projection, v[cornerindex], temp);
10356 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10357 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10358 // calculate distance fade from the projection origin
10359 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10360 f = bound(0.0f, f, 1.0f);
10361 c[cornerindex][0] = r * f;
10362 c[cornerindex][1] = g * f;
10363 c[cornerindex][2] = b * f;
10364 c[cornerindex][3] = 1.0f;
10365 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10368 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);
10370 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10371 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);
10373 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)
10375 matrix4x4_t projection;
10376 decalsystem_t *decalsystem;
10379 const msurface_t *surface;
10380 const msurface_t *surfaces;
10381 const int *surfacelist;
10382 const texture_t *texture;
10384 int numsurfacelist;
10385 int surfacelistindex;
10388 float localorigin[3];
10389 float localnormal[3];
10390 float localmins[3];
10391 float localmaxs[3];
10394 float planes[6][4];
10397 int bih_triangles_count;
10398 int bih_triangles[256];
10399 int bih_surfaces[256];
10401 decalsystem = &ent->decalsystem;
10402 model = ent->model;
10403 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10405 R_DecalSystem_Reset(&ent->decalsystem);
10409 if (!model->brush.data_leafs && !cl_decals_models.integer)
10411 if (decalsystem->model)
10412 R_DecalSystem_Reset(decalsystem);
10416 if (decalsystem->model != model)
10417 R_DecalSystem_Reset(decalsystem);
10418 decalsystem->model = model;
10420 RSurf_ActiveModelEntity(ent, true, false, false);
10422 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10423 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10424 VectorNormalize(localnormal);
10425 localsize = worldsize*rsurface.inversematrixscale;
10426 localmins[0] = localorigin[0] - localsize;
10427 localmins[1] = localorigin[1] - localsize;
10428 localmins[2] = localorigin[2] - localsize;
10429 localmaxs[0] = localorigin[0] + localsize;
10430 localmaxs[1] = localorigin[1] + localsize;
10431 localmaxs[2] = localorigin[2] + localsize;
10433 //VectorCopy(localnormal, planes[4]);
10434 //VectorVectors(planes[4], planes[2], planes[0]);
10435 AnglesFromVectors(angles, localnormal, NULL, false);
10436 AngleVectors(angles, planes[0], planes[2], planes[4]);
10437 VectorNegate(planes[0], planes[1]);
10438 VectorNegate(planes[2], planes[3]);
10439 VectorNegate(planes[4], planes[5]);
10440 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10441 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10442 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10443 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10444 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10445 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10450 matrix4x4_t forwardprojection;
10451 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10452 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10457 float projectionvector[4][3];
10458 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10459 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10460 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10461 projectionvector[0][0] = planes[0][0] * ilocalsize;
10462 projectionvector[0][1] = planes[1][0] * ilocalsize;
10463 projectionvector[0][2] = planes[2][0] * ilocalsize;
10464 projectionvector[1][0] = planes[0][1] * ilocalsize;
10465 projectionvector[1][1] = planes[1][1] * ilocalsize;
10466 projectionvector[1][2] = planes[2][1] * ilocalsize;
10467 projectionvector[2][0] = planes[0][2] * ilocalsize;
10468 projectionvector[2][1] = planes[1][2] * ilocalsize;
10469 projectionvector[2][2] = planes[2][2] * ilocalsize;
10470 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10471 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10472 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10473 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10477 dynamic = model->surfmesh.isanimated;
10478 numsurfacelist = model->nummodelsurfaces;
10479 surfacelist = model->sortedmodelsurfaces;
10480 surfaces = model->data_surfaces;
10483 bih_triangles_count = -1;
10486 if(model->render_bih.numleafs)
10487 bih = &model->render_bih;
10488 else if(model->collision_bih.numleafs)
10489 bih = &model->collision_bih;
10492 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10493 if(bih_triangles_count == 0)
10495 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10497 if(bih_triangles_count > 0)
10499 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10501 surfaceindex = bih_surfaces[triangleindex];
10502 surface = surfaces + surfaceindex;
10503 texture = surface->texture;
10504 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10506 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10508 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10513 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10515 surfaceindex = surfacelist[surfacelistindex];
10516 surface = surfaces + surfaceindex;
10517 // check cull box first because it rejects more than any other check
10518 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10520 // skip transparent surfaces
10521 texture = surface->texture;
10522 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10524 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10526 numtriangles = surface->num_triangles;
10527 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10528 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10533 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10534 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)
10536 int renderentityindex;
10537 float worldmins[3];
10538 float worldmaxs[3];
10539 entity_render_t *ent;
10541 if (!cl_decals_newsystem.integer)
10544 worldmins[0] = worldorigin[0] - worldsize;
10545 worldmins[1] = worldorigin[1] - worldsize;
10546 worldmins[2] = worldorigin[2] - worldsize;
10547 worldmaxs[0] = worldorigin[0] + worldsize;
10548 worldmaxs[1] = worldorigin[1] + worldsize;
10549 worldmaxs[2] = worldorigin[2] + worldsize;
10551 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10553 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10555 ent = r_refdef.scene.entities[renderentityindex];
10556 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10559 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10563 typedef struct r_decalsystem_splatqueue_s
10565 vec3_t worldorigin;
10566 vec3_t worldnormal;
10572 r_decalsystem_splatqueue_t;
10574 int r_decalsystem_numqueued = 0;
10575 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10577 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)
10579 r_decalsystem_splatqueue_t *queue;
10581 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10584 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10585 VectorCopy(worldorigin, queue->worldorigin);
10586 VectorCopy(worldnormal, queue->worldnormal);
10587 Vector4Set(queue->color, r, g, b, a);
10588 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10589 queue->worldsize = worldsize;
10590 queue->decalsequence = cl.decalsequence++;
10593 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10596 r_decalsystem_splatqueue_t *queue;
10598 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10599 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);
10600 r_decalsystem_numqueued = 0;
10603 extern cvar_t cl_decals_max;
10604 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10607 decalsystem_t *decalsystem = &ent->decalsystem;
10614 if (!decalsystem->numdecals)
10617 if (r_showsurfaces.integer)
10620 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10622 R_DecalSystem_Reset(decalsystem);
10626 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10627 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10629 if (decalsystem->lastupdatetime)
10630 frametime = (cl.time - decalsystem->lastupdatetime);
10633 decalsystem->lastupdatetime = cl.time;
10634 decal = decalsystem->decals;
10635 numdecals = decalsystem->numdecals;
10637 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10639 if (decal->color4f[0][3])
10641 decal->lived += frametime;
10642 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10644 memset(decal, 0, sizeof(*decal));
10645 if (decalsystem->freedecal > i)
10646 decalsystem->freedecal = i;
10650 decal = decalsystem->decals;
10651 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10654 // collapse the array by shuffling the tail decals into the gaps
10657 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10658 decalsystem->freedecal++;
10659 if (decalsystem->freedecal == numdecals)
10661 decal[decalsystem->freedecal] = decal[--numdecals];
10664 decalsystem->numdecals = numdecals;
10666 if (numdecals <= 0)
10668 // if there are no decals left, reset decalsystem
10669 R_DecalSystem_Reset(decalsystem);
10673 extern skinframe_t *decalskinframe;
10674 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10677 decalsystem_t *decalsystem = &ent->decalsystem;
10686 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10689 numdecals = decalsystem->numdecals;
10693 if (r_showsurfaces.integer)
10696 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10698 R_DecalSystem_Reset(decalsystem);
10702 // if the model is static it doesn't matter what value we give for
10703 // wantnormals and wanttangents, so this logic uses only rules applicable
10704 // to a model, knowing that they are meaningless otherwise
10705 if (ent == r_refdef.scene.worldentity)
10706 RSurf_ActiveWorldEntity();
10708 RSurf_ActiveModelEntity(ent, false, false, false);
10710 decalsystem->lastupdatetime = cl.time;
10711 decal = decalsystem->decals;
10713 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10715 // update vertex positions for animated models
10716 v3f = decalsystem->vertex3f;
10717 c4f = decalsystem->color4f;
10718 t2f = decalsystem->texcoord2f;
10719 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10721 if (!decal->color4f[0][3])
10724 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10727 // update color values for fading decals
10728 if (decal->lived >= cl_decals_time.value)
10729 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10733 c4f[ 0] = decal->color4f[0][0] * alpha;
10734 c4f[ 1] = decal->color4f[0][1] * alpha;
10735 c4f[ 2] = decal->color4f[0][2] * alpha;
10737 c4f[ 4] = decal->color4f[1][0] * alpha;
10738 c4f[ 5] = decal->color4f[1][1] * alpha;
10739 c4f[ 6] = decal->color4f[1][2] * alpha;
10741 c4f[ 8] = decal->color4f[2][0] * alpha;
10742 c4f[ 9] = decal->color4f[2][1] * alpha;
10743 c4f[10] = decal->color4f[2][2] * alpha;
10746 t2f[0] = decal->texcoord2f[0][0];
10747 t2f[1] = decal->texcoord2f[0][1];
10748 t2f[2] = decal->texcoord2f[1][0];
10749 t2f[3] = decal->texcoord2f[1][1];
10750 t2f[4] = decal->texcoord2f[2][0];
10751 t2f[5] = decal->texcoord2f[2][1];
10753 // update vertex positions for animated models
10754 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10756 e = rsurface.modelelement3i + 3*decal->triangleindex;
10757 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10758 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10759 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10763 VectorCopy(decal->vertex3f[0], v3f);
10764 VectorCopy(decal->vertex3f[1], v3f + 3);
10765 VectorCopy(decal->vertex3f[2], v3f + 6);
10768 if (r_refdef.fogenabled)
10770 alpha = RSurf_FogVertex(v3f);
10771 VectorScale(c4f, alpha, c4f);
10772 alpha = RSurf_FogVertex(v3f + 3);
10773 VectorScale(c4f + 4, alpha, c4f + 4);
10774 alpha = RSurf_FogVertex(v3f + 6);
10775 VectorScale(c4f + 8, alpha, c4f + 8);
10786 r_refdef.stats.drawndecals += numtris;
10788 // now render the decals all at once
10789 // (this assumes they all use one particle font texture!)
10790 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);
10791 // R_Mesh_ResetTextureState();
10792 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10793 GL_DepthMask(false);
10794 GL_DepthRange(0, 1);
10795 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10796 GL_DepthTest(true);
10797 GL_CullFace(GL_NONE);
10798 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10799 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10800 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10804 static void R_DrawModelDecals(void)
10808 // fade faster when there are too many decals
10809 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10810 for (i = 0;i < r_refdef.scene.numentities;i++)
10811 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10813 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10814 for (i = 0;i < r_refdef.scene.numentities;i++)
10815 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10816 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10818 R_DecalSystem_ApplySplatEntitiesQueue();
10820 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10821 for (i = 0;i < r_refdef.scene.numentities;i++)
10822 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10824 r_refdef.stats.totaldecals += numdecals;
10826 if (r_showsurfaces.integer)
10829 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10831 for (i = 0;i < r_refdef.scene.numentities;i++)
10833 if (!r_refdef.viewcache.entityvisible[i])
10835 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10836 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10840 extern cvar_t mod_collision_bih;
10841 void R_DrawDebugModel(void)
10843 entity_render_t *ent = rsurface.entity;
10844 int i, j, k, l, flagsmask;
10845 const msurface_t *surface;
10846 dp_model_t *model = ent->model;
10849 switch(vid.renderpath)
10851 case RENDERPATH_GL11:
10852 case RENDERPATH_GL13:
10853 case RENDERPATH_GL20:
10855 case RENDERPATH_D3D9:
10856 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10858 case RENDERPATH_D3D10:
10859 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10861 case RENDERPATH_D3D11:
10862 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10864 case RENDERPATH_SOFT:
10865 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10867 case RENDERPATH_GLES2:
10868 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10872 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10874 // R_Mesh_ResetTextureState();
10875 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10876 GL_DepthRange(0, 1);
10877 GL_DepthTest(!r_showdisabledepthtest.integer);
10878 GL_DepthMask(false);
10879 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10881 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10885 qboolean cullbox = ent == r_refdef.scene.worldentity;
10886 const q3mbrush_t *brush;
10887 const bih_t *bih = &model->collision_bih;
10888 const bih_leaf_t *bihleaf;
10889 float vertex3f[3][3];
10890 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10892 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10894 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10896 switch (bihleaf->type)
10899 brush = model->brush.data_brushes + bihleaf->itemindex;
10900 if (brush->colbrushf && brush->colbrushf->numtriangles)
10902 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);
10903 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10904 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10907 case BIH_COLLISIONTRIANGLE:
10908 triangleindex = bihleaf->itemindex;
10909 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10910 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10911 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10912 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
10913 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10914 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10916 case BIH_RENDERTRIANGLE:
10917 triangleindex = bihleaf->itemindex;
10918 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10919 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10920 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10921 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);
10922 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10923 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10929 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10931 if (r_showtris.integer || (r_shownormals.value != 0))
10933 if (r_showdisabledepthtest.integer)
10935 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10936 GL_DepthMask(false);
10940 GL_BlendFunc(GL_ONE, GL_ZERO);
10941 GL_DepthMask(true);
10943 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10945 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10947 rsurface.texture = R_GetCurrentTexture(surface->texture);
10948 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10950 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10951 if (r_showtris.value > 0)
10953 if (!rsurface.texture->currentlayers->depthmask)
10954 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10955 else if (ent == r_refdef.scene.worldentity)
10956 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10958 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10959 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10960 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10962 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10965 if (r_shownormals.value < 0)
10967 qglBegin(GL_LINES);
10968 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10970 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10971 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10972 qglVertex3f(v[0], v[1], v[2]);
10973 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10974 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10975 qglVertex3f(v[0], v[1], v[2]);
10980 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10982 qglBegin(GL_LINES);
10983 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10985 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10986 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10987 qglVertex3f(v[0], v[1], v[2]);
10988 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10989 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10990 qglVertex3f(v[0], v[1], v[2]);
10994 qglBegin(GL_LINES);
10995 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10997 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10998 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10999 qglVertex3f(v[0], v[1], v[2]);
11000 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11001 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11002 qglVertex3f(v[0], v[1], v[2]);
11006 qglBegin(GL_LINES);
11007 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11009 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11010 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11011 qglVertex3f(v[0], v[1], v[2]);
11012 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11013 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11014 qglVertex3f(v[0], v[1], v[2]);
11021 rsurface.texture = NULL;
11025 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11026 int r_maxsurfacelist = 0;
11027 const msurface_t **r_surfacelist = NULL;
11028 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11030 int i, j, endj, flagsmask;
11031 dp_model_t *model = r_refdef.scene.worldmodel;
11032 msurface_t *surfaces;
11033 unsigned char *update;
11034 int numsurfacelist = 0;
11038 if (r_maxsurfacelist < model->num_surfaces)
11040 r_maxsurfacelist = model->num_surfaces;
11042 Mem_Free((msurface_t**)r_surfacelist);
11043 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11046 RSurf_ActiveWorldEntity();
11048 surfaces = model->data_surfaces;
11049 update = model->brushq1.lightmapupdateflags;
11051 // update light styles on this submodel
11052 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11054 model_brush_lightstyleinfo_t *style;
11055 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11057 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11059 int *list = style->surfacelist;
11060 style->value = r_refdef.scene.lightstylevalue[style->style];
11061 for (j = 0;j < style->numsurfaces;j++)
11062 update[list[j]] = true;
11067 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11071 R_DrawDebugModel();
11072 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11076 rsurface.lightmaptexture = NULL;
11077 rsurface.deluxemaptexture = NULL;
11078 rsurface.uselightmaptexture = false;
11079 rsurface.texture = NULL;
11080 rsurface.rtlight = NULL;
11081 numsurfacelist = 0;
11082 // add visible surfaces to draw list
11083 for (i = 0;i < model->nummodelsurfaces;i++)
11085 j = model->sortedmodelsurfaces[i];
11086 if (r_refdef.viewcache.world_surfacevisible[j])
11087 r_surfacelist[numsurfacelist++] = surfaces + j;
11089 // update lightmaps if needed
11090 if (model->brushq1.firstrender)
11092 model->brushq1.firstrender = false;
11093 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11095 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11099 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11100 if (r_refdef.viewcache.world_surfacevisible[j])
11102 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11104 // don't do anything if there were no surfaces
11105 if (!numsurfacelist)
11107 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11110 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11112 // add to stats if desired
11113 if (r_speeds.integer && !skysurfaces && !depthonly)
11115 r_refdef.stats.world_surfaces += numsurfacelist;
11116 for (j = 0;j < numsurfacelist;j++)
11117 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11120 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11123 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11125 int i, j, endj, flagsmask;
11126 dp_model_t *model = ent->model;
11127 msurface_t *surfaces;
11128 unsigned char *update;
11129 int numsurfacelist = 0;
11133 if (r_maxsurfacelist < model->num_surfaces)
11135 r_maxsurfacelist = model->num_surfaces;
11137 Mem_Free((msurface_t **)r_surfacelist);
11138 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11141 // if the model is static it doesn't matter what value we give for
11142 // wantnormals and wanttangents, so this logic uses only rules applicable
11143 // to a model, knowing that they are meaningless otherwise
11144 if (ent == r_refdef.scene.worldentity)
11145 RSurf_ActiveWorldEntity();
11146 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11147 RSurf_ActiveModelEntity(ent, false, false, false);
11149 RSurf_ActiveModelEntity(ent, true, true, true);
11150 else if (depthonly)
11152 switch (vid.renderpath)
11154 case RENDERPATH_GL20:
11155 case RENDERPATH_D3D9:
11156 case RENDERPATH_D3D10:
11157 case RENDERPATH_D3D11:
11158 case RENDERPATH_SOFT:
11159 case RENDERPATH_GLES2:
11160 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11162 case RENDERPATH_GL13:
11163 case RENDERPATH_GL11:
11164 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11170 switch (vid.renderpath)
11172 case RENDERPATH_GL20:
11173 case RENDERPATH_D3D9:
11174 case RENDERPATH_D3D10:
11175 case RENDERPATH_D3D11:
11176 case RENDERPATH_SOFT:
11177 case RENDERPATH_GLES2:
11178 RSurf_ActiveModelEntity(ent, true, true, false);
11180 case RENDERPATH_GL13:
11181 case RENDERPATH_GL11:
11182 RSurf_ActiveModelEntity(ent, true, false, false);
11187 surfaces = model->data_surfaces;
11188 update = model->brushq1.lightmapupdateflags;
11190 // update light styles
11191 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11193 model_brush_lightstyleinfo_t *style;
11194 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11196 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11198 int *list = style->surfacelist;
11199 style->value = r_refdef.scene.lightstylevalue[style->style];
11200 for (j = 0;j < style->numsurfaces;j++)
11201 update[list[j]] = true;
11206 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11210 R_DrawDebugModel();
11211 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11215 rsurface.lightmaptexture = NULL;
11216 rsurface.deluxemaptexture = NULL;
11217 rsurface.uselightmaptexture = false;
11218 rsurface.texture = NULL;
11219 rsurface.rtlight = NULL;
11220 numsurfacelist = 0;
11221 // add visible surfaces to draw list
11222 for (i = 0;i < model->nummodelsurfaces;i++)
11223 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11224 // don't do anything if there were no surfaces
11225 if (!numsurfacelist)
11227 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11230 // update lightmaps if needed
11234 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11239 R_BuildLightMap(ent, surfaces + j);
11244 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11246 R_BuildLightMap(ent, surfaces + j);
11247 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11249 // add to stats if desired
11250 if (r_speeds.integer && !skysurfaces && !depthonly)
11252 r_refdef.stats.entities_surfaces += numsurfacelist;
11253 for (j = 0;j < numsurfacelist;j++)
11254 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11257 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11260 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11262 static texture_t texture;
11263 static msurface_t surface;
11264 const msurface_t *surfacelist = &surface;
11266 // fake enough texture and surface state to render this geometry
11268 texture.update_lastrenderframe = -1; // regenerate this texture
11269 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11270 texture.currentskinframe = skinframe;
11271 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11272 texture.offsetmapping = OFFSETMAPPING_OFF;
11273 texture.offsetscale = 1;
11274 texture.specularscalemod = 1;
11275 texture.specularpowermod = 1;
11277 surface.texture = &texture;
11278 surface.num_triangles = numtriangles;
11279 surface.num_firsttriangle = firsttriangle;
11280 surface.num_vertices = numvertices;
11281 surface.num_firstvertex = firstvertex;
11284 rsurface.texture = R_GetCurrentTexture(surface.texture);
11285 rsurface.lightmaptexture = NULL;
11286 rsurface.deluxemaptexture = NULL;
11287 rsurface.uselightmaptexture = false;
11288 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11291 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)
11293 static msurface_t surface;
11294 const msurface_t *surfacelist = &surface;
11296 // fake enough texture and surface state to render this geometry
11297 surface.texture = texture;
11298 surface.num_triangles = numtriangles;
11299 surface.num_firsttriangle = firsttriangle;
11300 surface.num_vertices = numvertices;
11301 surface.num_firstvertex = firstvertex;
11304 rsurface.texture = R_GetCurrentTexture(surface.texture);
11305 rsurface.lightmaptexture = NULL;
11306 rsurface.deluxemaptexture = NULL;
11307 rsurface.uselightmaptexture = false;
11308 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);