2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
146 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
148 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
149 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
150 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
159 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
160 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
161 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
162 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
163 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
164 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
166 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
167 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
168 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
169 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
171 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
172 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
173 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
174 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
175 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
176 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
177 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
179 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
180 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
181 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
182 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
183 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
184 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
185 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
186 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
188 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
190 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
192 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
194 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
196 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
197 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
198 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
199 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
200 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
201 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
202 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
203 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
204 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
206 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
207 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
209 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
211 extern cvar_t v_glslgamma;
213 extern qboolean v_flipped_state;
215 static struct r_bloomstate_s
220 int bloomwidth, bloomheight;
222 int screentexturewidth, screentextureheight;
223 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
225 int bloomtexturewidth, bloomtextureheight;
226 rtexture_t *texture_bloom;
228 // arrays for rendering the screen passes
229 float screentexcoord2f[8];
230 float bloomtexcoord2f[8];
231 float offsettexcoord2f[8];
233 r_viewport_t viewport;
237 r_waterstate_t r_waterstate;
239 /// shadow volume bsp struct with automatically growing nodes buffer
242 rtexture_t *r_texture_blanknormalmap;
243 rtexture_t *r_texture_white;
244 rtexture_t *r_texture_grey128;
245 rtexture_t *r_texture_black;
246 rtexture_t *r_texture_notexture;
247 rtexture_t *r_texture_whitecube;
248 rtexture_t *r_texture_normalizationcube;
249 rtexture_t *r_texture_fogattenuation;
250 rtexture_t *r_texture_fogheighttexture;
251 rtexture_t *r_texture_gammaramps;
252 unsigned int r_texture_gammaramps_serial;
253 //rtexture_t *r_texture_fogintensity;
254 rtexture_t *r_texture_reflectcube;
256 // TODO: hash lookups?
257 typedef struct cubemapinfo_s
264 int r_texture_numcubemaps;
265 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
267 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
268 unsigned int r_numqueries;
269 unsigned int r_maxqueries;
271 typedef struct r_qwskincache_s
273 char name[MAX_QPATH];
274 skinframe_t *skinframe;
278 static r_qwskincache_t *r_qwskincache;
279 static int r_qwskincache_size;
281 /// vertex coordinates for a quad that covers the screen exactly
282 extern const float r_screenvertex3f[12];
283 extern const float r_d3dscreenvertex3f[12];
284 const float r_screenvertex3f[12] =
291 const float r_d3dscreenvertex3f[12] =
299 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
302 for (i = 0;i < verts;i++)
313 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
316 for (i = 0;i < verts;i++)
326 // FIXME: move this to client?
329 if (gamemode == GAME_NEHAHRA)
331 Cvar_Set("gl_fogenable", "0");
332 Cvar_Set("gl_fogdensity", "0.2");
333 Cvar_Set("gl_fogred", "0.3");
334 Cvar_Set("gl_foggreen", "0.3");
335 Cvar_Set("gl_fogblue", "0.3");
337 r_refdef.fog_density = 0;
338 r_refdef.fog_red = 0;
339 r_refdef.fog_green = 0;
340 r_refdef.fog_blue = 0;
341 r_refdef.fog_alpha = 1;
342 r_refdef.fog_start = 0;
343 r_refdef.fog_end = 16384;
344 r_refdef.fog_height = 1<<30;
345 r_refdef.fog_fadedepth = 128;
346 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
349 static void R_BuildBlankTextures(void)
351 unsigned char data[4];
352 data[2] = 128; // normal X
353 data[1] = 128; // normal Y
354 data[0] = 255; // normal Z
355 data[3] = 128; // height
356 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 static void R_BuildNoTexture(void)
377 unsigned char pix[16][16][4];
378 // this makes a light grey/dark grey checkerboard texture
379 for (y = 0;y < 16;y++)
381 for (x = 0;x < 16;x++)
383 if ((y < 8) ^ (x < 8))
399 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
402 static void R_BuildWhiteCube(void)
404 unsigned char data[6*1*1*4];
405 memset(data, 255, sizeof(data));
406 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
409 static void R_BuildNormalizationCube(void)
413 vec_t s, t, intensity;
416 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
417 for (side = 0;side < 6;side++)
419 for (y = 0;y < NORMSIZE;y++)
421 for (x = 0;x < NORMSIZE;x++)
423 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459 intensity = 127.0f / sqrt(DotProduct(v, v));
460 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
461 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
462 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
463 data[((side*64+y)*64+x)*4+3] = 255;
467 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
471 static void R_BuildFogTexture(void)
475 unsigned char data1[FOGWIDTH][4];
476 //unsigned char data2[FOGWIDTH][4];
479 r_refdef.fogmasktable_start = r_refdef.fog_start;
480 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
481 r_refdef.fogmasktable_range = r_refdef.fogrange;
482 r_refdef.fogmasktable_density = r_refdef.fog_density;
484 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
485 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
487 d = (x * r - r_refdef.fogmasktable_start);
488 if(developer_extra.integer)
489 Con_DPrintf("%f ", d);
491 if (r_fog_exp2.integer)
492 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
494 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
495 if(developer_extra.integer)
496 Con_DPrintf(" : %f ", alpha);
497 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
498 if(developer_extra.integer)
499 Con_DPrintf(" = %f\n", alpha);
500 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
503 for (x = 0;x < FOGWIDTH;x++)
505 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
510 //data2[x][0] = 255 - b;
511 //data2[x][1] = 255 - b;
512 //data2[x][2] = 255 - b;
515 if (r_texture_fogattenuation)
517 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
522 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
523 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
527 static void R_BuildFogHeightTexture(void)
529 unsigned char *inpixels;
537 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
538 if (r_refdef.fogheighttexturename[0])
539 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
542 r_refdef.fog_height_tablesize = 0;
543 if (r_texture_fogheighttexture)
544 R_FreeTexture(r_texture_fogheighttexture);
545 r_texture_fogheighttexture = NULL;
546 if (r_refdef.fog_height_table2d)
547 Mem_Free(r_refdef.fog_height_table2d);
548 r_refdef.fog_height_table2d = NULL;
549 if (r_refdef.fog_height_table1d)
550 Mem_Free(r_refdef.fog_height_table1d);
551 r_refdef.fog_height_table1d = NULL;
555 r_refdef.fog_height_tablesize = size;
556 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
557 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
558 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
560 // LordHavoc: now the magic - what is that table2d for? it is a cooked
561 // average fog color table accounting for every fog layer between a point
562 // and the camera. (Note: attenuation is handled separately!)
563 for (y = 0;y < size;y++)
565 for (x = 0;x < size;x++)
571 for (j = x;j <= y;j++)
573 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
579 for (j = x;j >= y;j--)
581 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
586 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
588 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
589 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
592 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
595 //=======================================================================================================================================================
597 static const char *builtinshaderstring =
598 #include "shader_glsl.h"
601 const char *builtinhlslshaderstring =
602 #include "shader_hlsl.h"
605 char *glslshaderstring = NULL;
606 char *hlslshaderstring = NULL;
608 //=======================================================================================================================================================
610 typedef struct shaderpermutationinfo_s
615 shaderpermutationinfo_t;
617 typedef struct shadermodeinfo_s
619 const char *vertexfilename;
620 const char *geometryfilename;
621 const char *fragmentfilename;
627 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
628 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
630 {"#define USEDIFFUSE\n", " diffuse"},
631 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
632 {"#define USEVIEWTINT\n", " viewtint"},
633 {"#define USECOLORMAPPING\n", " colormapping"},
634 {"#define USESATURATION\n", " saturation"},
635 {"#define USEFOGINSIDE\n", " foginside"},
636 {"#define USEFOGOUTSIDE\n", " fogoutside"},
637 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
638 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
639 {"#define USEGAMMARAMPS\n", " gammaramps"},
640 {"#define USECUBEFILTER\n", " cubefilter"},
641 {"#define USEGLOW\n", " glow"},
642 {"#define USEBLOOM\n", " bloom"},
643 {"#define USESPECULAR\n", " specular"},
644 {"#define USEPOSTPROCESSING\n", " postprocessing"},
645 {"#define USEREFLECTION\n", " reflection"},
646 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
647 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
648 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
649 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
650 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
651 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
652 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
653 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
654 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
655 {"#define USEALPHAKILL\n", " alphakill"},
656 {"#define USEREFLECTCUBE\n", " reflectcube"},
657 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
658 {"#define USEBOUNCEGRID\n", " bouncegrid"},
661 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
662 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
664 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
665 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
666 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
667 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
682 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
684 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
685 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 struct r_glsl_permutation_s;
703 typedef struct r_glsl_permutation_s
706 struct r_glsl_permutation_s *hashnext;
708 unsigned int permutation;
710 /// indicates if we have tried compiling this permutation already
712 /// 0 if compilation failed
714 // texture units assigned to each detected uniform
715 int tex_Texture_First;
716 int tex_Texture_Second;
717 int tex_Texture_GammaRamps;
718 int tex_Texture_Normal;
719 int tex_Texture_Color;
720 int tex_Texture_Gloss;
721 int tex_Texture_Glow;
722 int tex_Texture_SecondaryNormal;
723 int tex_Texture_SecondaryColor;
724 int tex_Texture_SecondaryGloss;
725 int tex_Texture_SecondaryGlow;
726 int tex_Texture_Pants;
727 int tex_Texture_Shirt;
728 int tex_Texture_FogHeightTexture;
729 int tex_Texture_FogMask;
730 int tex_Texture_Lightmap;
731 int tex_Texture_Deluxemap;
732 int tex_Texture_Attenuation;
733 int tex_Texture_Cube;
734 int tex_Texture_Refraction;
735 int tex_Texture_Reflection;
736 int tex_Texture_ShadowMap2D;
737 int tex_Texture_CubeProjection;
738 int tex_Texture_ScreenDepth;
739 int tex_Texture_ScreenNormalMap;
740 int tex_Texture_ScreenDiffuse;
741 int tex_Texture_ScreenSpecular;
742 int tex_Texture_ReflectMask;
743 int tex_Texture_ReflectCube;
744 int tex_Texture_BounceGrid;
745 /// locations of detected uniforms in program object, or -1 if not found
746 int loc_Texture_First;
747 int loc_Texture_Second;
748 int loc_Texture_GammaRamps;
749 int loc_Texture_Normal;
750 int loc_Texture_Color;
751 int loc_Texture_Gloss;
752 int loc_Texture_Glow;
753 int loc_Texture_SecondaryNormal;
754 int loc_Texture_SecondaryColor;
755 int loc_Texture_SecondaryGloss;
756 int loc_Texture_SecondaryGlow;
757 int loc_Texture_Pants;
758 int loc_Texture_Shirt;
759 int loc_Texture_FogHeightTexture;
760 int loc_Texture_FogMask;
761 int loc_Texture_Lightmap;
762 int loc_Texture_Deluxemap;
763 int loc_Texture_Attenuation;
764 int loc_Texture_Cube;
765 int loc_Texture_Refraction;
766 int loc_Texture_Reflection;
767 int loc_Texture_ShadowMap2D;
768 int loc_Texture_CubeProjection;
769 int loc_Texture_ScreenDepth;
770 int loc_Texture_ScreenNormalMap;
771 int loc_Texture_ScreenDiffuse;
772 int loc_Texture_ScreenSpecular;
773 int loc_Texture_ReflectMask;
774 int loc_Texture_ReflectCube;
775 int loc_Texture_BounceGrid;
777 int loc_BloomBlur_Parameters;
779 int loc_Color_Ambient;
780 int loc_Color_Diffuse;
781 int loc_Color_Specular;
785 int loc_DeferredColor_Ambient;
786 int loc_DeferredColor_Diffuse;
787 int loc_DeferredColor_Specular;
788 int loc_DeferredMod_Diffuse;
789 int loc_DeferredMod_Specular;
790 int loc_DistortScaleRefractReflect;
793 int loc_FogHeightFade;
795 int loc_FogPlaneViewDist;
796 int loc_FogRangeRecip;
799 int loc_LightPosition;
800 int loc_OffsetMapping_ScaleSteps;
802 int loc_ReflectColor;
803 int loc_ReflectFactor;
804 int loc_ReflectOffset;
805 int loc_RefractColor;
807 int loc_ScreenCenterRefractReflect;
808 int loc_ScreenScaleRefractReflect;
809 int loc_ScreenToDepth;
810 int loc_ShadowMap_Parameters;
811 int loc_ShadowMap_TextureScale;
812 int loc_SpecularPower;
817 int loc_ViewTintColor;
819 int loc_ModelToLight;
821 int loc_BackgroundTexMatrix;
822 int loc_ModelViewProjectionMatrix;
823 int loc_ModelViewMatrix;
824 int loc_PixelToScreenTexCoord;
825 int loc_ModelToReflectCube;
826 int loc_ShadowMapMatrix;
827 int loc_BloomColorSubtract;
828 int loc_NormalmapScrollBlend;
829 int loc_BounceGridMatrix;
830 int loc_BounceGridIntensity;
832 r_glsl_permutation_t;
834 #define SHADERPERMUTATION_HASHSIZE 256
837 // non-degradable "lightweight" shader parameters to keep the permutations simpler
838 // these can NOT degrade! only use for simple stuff
841 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
842 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
843 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
844 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
845 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
846 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
848 #define SHADERSTATICPARMS_COUNT 6
850 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
851 static int shaderstaticparms_count = 0;
853 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
854 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
855 qboolean R_CompileShader_CheckStaticParms(void)
857 static int r_compileshader_staticparms_save[1];
858 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
859 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
862 if (r_glsl_saturation_redcompensate.integer)
863 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
864 if (r_shadow_glossexact.integer)
865 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
866 if (r_glsl_postprocess.integer)
868 if (r_glsl_postprocess_uservec1_enable.integer)
869 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
870 if (r_glsl_postprocess_uservec2_enable.integer)
871 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
872 if (r_glsl_postprocess_uservec3_enable.integer)
873 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
874 if (r_glsl_postprocess_uservec4_enable.integer)
875 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
877 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
880 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
881 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
882 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
884 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
885 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
887 shaderstaticparms_count = 0;
890 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
891 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
892 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
893 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
894 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
895 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
898 /// information about each possible shader permutation
899 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
900 /// currently selected permutation
901 r_glsl_permutation_t *r_glsl_permutation;
902 /// storage for permutations linked in the hash table
903 memexpandablearray_t r_glsl_permutationarray;
905 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
907 //unsigned int hashdepth = 0;
908 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
909 r_glsl_permutation_t *p;
910 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
912 if (p->mode == mode && p->permutation == permutation)
914 //if (hashdepth > 10)
915 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
920 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
922 p->permutation = permutation;
923 p->hashnext = r_glsl_permutationhash[mode][hashindex];
924 r_glsl_permutationhash[mode][hashindex] = p;
925 //if (hashdepth > 10)
926 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
930 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
933 if (!filename || !filename[0])
935 if (!strcmp(filename, "glsl/default.glsl"))
937 if (!glslshaderstring)
939 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
940 if (glslshaderstring)
941 Con_DPrintf("Loading shaders from file %s...\n", filename);
943 glslshaderstring = (char *)builtinshaderstring;
945 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
946 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
949 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952 if (printfromdisknotice)
953 Con_DPrintf("from disk %s... ", filename);
959 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
963 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
964 char *vertexstring, *geometrystring, *fragmentstring;
965 char permutationname[256];
966 int vertstrings_count = 0;
967 int geomstrings_count = 0;
968 int fragstrings_count = 0;
969 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
970 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
971 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
978 permutationname[0] = 0;
979 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
980 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
981 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
983 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
985 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
986 if(vid.support.gl20shaders130)
988 vertstrings_list[vertstrings_count++] = "#version 130\n";
989 geomstrings_list[geomstrings_count++] = "#version 130\n";
990 fragstrings_list[fragstrings_count++] = "#version 130\n";
993 // the first pretext is which type of shader to compile as
994 // (later these will all be bound together as a program object)
995 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
996 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
997 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
999 // the second pretext is the mode (for example a light source)
1000 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1001 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1002 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1003 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1005 // now add all the permutation pretexts
1006 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1008 if (permutation & (1<<i))
1010 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1011 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1012 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1013 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1017 // keep line numbers correct
1018 vertstrings_list[vertstrings_count++] = "\n";
1019 geomstrings_list[geomstrings_count++] = "\n";
1020 fragstrings_list[fragstrings_count++] = "\n";
1025 R_CompileShader_AddStaticParms(mode, permutation);
1026 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1027 vertstrings_count += shaderstaticparms_count;
1028 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1029 geomstrings_count += shaderstaticparms_count;
1030 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1031 fragstrings_count += shaderstaticparms_count;
1033 // now append the shader text itself
1034 vertstrings_list[vertstrings_count++] = vertexstring;
1035 geomstrings_list[geomstrings_count++] = geometrystring;
1036 fragstrings_list[fragstrings_count++] = fragmentstring;
1038 // if any sources were NULL, clear the respective list
1040 vertstrings_count = 0;
1041 if (!geometrystring)
1042 geomstrings_count = 0;
1043 if (!fragmentstring)
1044 fragstrings_count = 0;
1046 // compile the shader program
1047 if (vertstrings_count + geomstrings_count + fragstrings_count)
1048 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1052 qglUseProgram(p->program);CHECKGLERROR
1053 // look up all the uniform variable names we care about, so we don't
1054 // have to look them up every time we set them
1056 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1057 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1058 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1059 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1060 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1061 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1062 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1063 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1064 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1065 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1066 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1067 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1068 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1069 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1070 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1071 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1072 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1073 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1074 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1075 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1076 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1077 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1078 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1079 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1080 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1081 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1082 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1083 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1084 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1085 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1086 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1087 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1088 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1089 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1090 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1091 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1092 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1093 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1094 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1095 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1096 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1097 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1098 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1099 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1100 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1101 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1102 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1103 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1104 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1105 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1106 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1107 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1108 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1109 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1110 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1111 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1112 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1113 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1114 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1115 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1116 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1117 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1118 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1119 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1120 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1121 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1122 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1123 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1124 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1125 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1126 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1127 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1128 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1129 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1130 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1131 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1132 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1133 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1134 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1135 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1136 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1137 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1138 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1139 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1140 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1141 // initialize the samplers to refer to the texture units we use
1142 p->tex_Texture_First = -1;
1143 p->tex_Texture_Second = -1;
1144 p->tex_Texture_GammaRamps = -1;
1145 p->tex_Texture_Normal = -1;
1146 p->tex_Texture_Color = -1;
1147 p->tex_Texture_Gloss = -1;
1148 p->tex_Texture_Glow = -1;
1149 p->tex_Texture_SecondaryNormal = -1;
1150 p->tex_Texture_SecondaryColor = -1;
1151 p->tex_Texture_SecondaryGloss = -1;
1152 p->tex_Texture_SecondaryGlow = -1;
1153 p->tex_Texture_Pants = -1;
1154 p->tex_Texture_Shirt = -1;
1155 p->tex_Texture_FogHeightTexture = -1;
1156 p->tex_Texture_FogMask = -1;
1157 p->tex_Texture_Lightmap = -1;
1158 p->tex_Texture_Deluxemap = -1;
1159 p->tex_Texture_Attenuation = -1;
1160 p->tex_Texture_Cube = -1;
1161 p->tex_Texture_Refraction = -1;
1162 p->tex_Texture_Reflection = -1;
1163 p->tex_Texture_ShadowMap2D = -1;
1164 p->tex_Texture_CubeProjection = -1;
1165 p->tex_Texture_ScreenDepth = -1;
1166 p->tex_Texture_ScreenNormalMap = -1;
1167 p->tex_Texture_ScreenDiffuse = -1;
1168 p->tex_Texture_ScreenSpecular = -1;
1169 p->tex_Texture_ReflectMask = -1;
1170 p->tex_Texture_ReflectCube = -1;
1171 p->tex_Texture_BounceGrid = -1;
1173 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1174 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1175 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1176 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1177 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1178 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1179 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1180 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1181 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1182 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1183 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1184 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1185 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1186 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1187 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1188 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1189 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1190 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1191 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1192 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1193 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1194 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1195 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1196 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1197 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1198 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1199 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1200 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1201 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1202 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1204 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1207 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1211 Mem_Free(vertexstring);
1213 Mem_Free(geometrystring);
1215 Mem_Free(fragmentstring);
1218 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1220 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1221 if (r_glsl_permutation != perm)
1223 r_glsl_permutation = perm;
1224 if (!r_glsl_permutation->program)
1226 if (!r_glsl_permutation->compiled)
1227 R_GLSL_CompilePermutation(perm, mode, permutation);
1228 if (!r_glsl_permutation->program)
1230 // remove features until we find a valid permutation
1232 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1234 // reduce i more quickly whenever it would not remove any bits
1235 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1236 if (!(permutation & j))
1239 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1240 if (!r_glsl_permutation->compiled)
1241 R_GLSL_CompilePermutation(perm, mode, permutation);
1242 if (r_glsl_permutation->program)
1245 if (i >= SHADERPERMUTATION_COUNT)
1247 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1248 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1249 qglUseProgram(0);CHECKGLERROR
1250 return; // no bit left to clear, entire mode is broken
1255 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1257 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1258 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1259 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1266 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1267 extern D3DCAPS9 vid_d3d9caps;
1270 struct r_hlsl_permutation_s;
1271 typedef struct r_hlsl_permutation_s
1273 /// hash lookup data
1274 struct r_hlsl_permutation_s *hashnext;
1276 unsigned int permutation;
1278 /// indicates if we have tried compiling this permutation already
1280 /// NULL if compilation failed
1281 IDirect3DVertexShader9 *vertexshader;
1282 IDirect3DPixelShader9 *pixelshader;
1284 r_hlsl_permutation_t;
1286 typedef enum D3DVSREGISTER_e
1288 D3DVSREGISTER_TexMatrix = 0, // float4x4
1289 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1290 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1291 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1292 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1293 D3DVSREGISTER_ModelToLight = 20, // float4x4
1294 D3DVSREGISTER_EyePosition = 24,
1295 D3DVSREGISTER_FogPlane = 25,
1296 D3DVSREGISTER_LightDir = 26,
1297 D3DVSREGISTER_LightPosition = 27,
1301 typedef enum D3DPSREGISTER_e
1303 D3DPSREGISTER_Alpha = 0,
1304 D3DPSREGISTER_BloomBlur_Parameters = 1,
1305 D3DPSREGISTER_ClientTime = 2,
1306 D3DPSREGISTER_Color_Ambient = 3,
1307 D3DPSREGISTER_Color_Diffuse = 4,
1308 D3DPSREGISTER_Color_Specular = 5,
1309 D3DPSREGISTER_Color_Glow = 6,
1310 D3DPSREGISTER_Color_Pants = 7,
1311 D3DPSREGISTER_Color_Shirt = 8,
1312 D3DPSREGISTER_DeferredColor_Ambient = 9,
1313 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1314 D3DPSREGISTER_DeferredColor_Specular = 11,
1315 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1316 D3DPSREGISTER_DeferredMod_Specular = 13,
1317 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1318 D3DPSREGISTER_EyePosition = 15, // unused
1319 D3DPSREGISTER_FogColor = 16,
1320 D3DPSREGISTER_FogHeightFade = 17,
1321 D3DPSREGISTER_FogPlane = 18,
1322 D3DPSREGISTER_FogPlaneViewDist = 19,
1323 D3DPSREGISTER_FogRangeRecip = 20,
1324 D3DPSREGISTER_LightColor = 21,
1325 D3DPSREGISTER_LightDir = 22, // unused
1326 D3DPSREGISTER_LightPosition = 23,
1327 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1328 D3DPSREGISTER_PixelSize = 25,
1329 D3DPSREGISTER_ReflectColor = 26,
1330 D3DPSREGISTER_ReflectFactor = 27,
1331 D3DPSREGISTER_ReflectOffset = 28,
1332 D3DPSREGISTER_RefractColor = 29,
1333 D3DPSREGISTER_Saturation = 30,
1334 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1335 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1336 D3DPSREGISTER_ScreenToDepth = 33,
1337 D3DPSREGISTER_ShadowMap_Parameters = 34,
1338 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1339 D3DPSREGISTER_SpecularPower = 36,
1340 D3DPSREGISTER_UserVec1 = 37,
1341 D3DPSREGISTER_UserVec2 = 38,
1342 D3DPSREGISTER_UserVec3 = 39,
1343 D3DPSREGISTER_UserVec4 = 40,
1344 D3DPSREGISTER_ViewTintColor = 41,
1345 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1346 D3DPSREGISTER_BloomColorSubtract = 43,
1347 D3DPSREGISTER_ViewToLight = 44, // float4x4
1348 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1349 D3DPSREGISTER_NormalmapScrollBlend = 52,
1354 /// information about each possible shader permutation
1355 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1356 /// currently selected permutation
1357 r_hlsl_permutation_t *r_hlsl_permutation;
1358 /// storage for permutations linked in the hash table
1359 memexpandablearray_t r_hlsl_permutationarray;
1361 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1363 //unsigned int hashdepth = 0;
1364 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1365 r_hlsl_permutation_t *p;
1366 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1368 if (p->mode == mode && p->permutation == permutation)
1370 //if (hashdepth > 10)
1371 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1376 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1378 p->permutation = permutation;
1379 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1380 r_hlsl_permutationhash[mode][hashindex] = p;
1381 //if (hashdepth > 10)
1382 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1386 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1389 if (!filename || !filename[0])
1391 if (!strcmp(filename, "hlsl/default.hlsl"))
1393 if (!hlslshaderstring)
1395 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1396 if (hlslshaderstring)
1397 Con_DPrintf("Loading shaders from file %s...\n", filename);
1399 hlslshaderstring = (char *)builtinhlslshaderstring;
1401 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1402 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1403 return shaderstring;
1405 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1408 if (printfromdisknotice)
1409 Con_DPrintf("from disk %s... ", filename);
1410 return shaderstring;
1412 return shaderstring;
1416 //#include <d3dx9shader.h>
1417 //#include <d3dx9mesh.h>
1419 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1421 DWORD *vsbin = NULL;
1422 DWORD *psbin = NULL;
1423 fs_offset_t vsbinsize;
1424 fs_offset_t psbinsize;
1425 // IDirect3DVertexShader9 *vs = NULL;
1426 // IDirect3DPixelShader9 *ps = NULL;
1427 ID3DXBuffer *vslog = NULL;
1428 ID3DXBuffer *vsbuffer = NULL;
1429 ID3DXConstantTable *vsconstanttable = NULL;
1430 ID3DXBuffer *pslog = NULL;
1431 ID3DXBuffer *psbuffer = NULL;
1432 ID3DXConstantTable *psconstanttable = NULL;
1435 char temp[MAX_INPUTLINE];
1436 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1437 qboolean debugshader = gl_paranoid.integer != 0;
1438 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1439 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1442 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1443 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1445 if ((!vsbin && vertstring) || (!psbin && fragstring))
1447 const char* dllnames_d3dx9 [] =
1471 dllhandle_t d3dx9_dll = NULL;
1472 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1473 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1474 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1475 dllfunction_t d3dx9_dllfuncs[] =
1477 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1478 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1479 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1482 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1484 DWORD shaderflags = 0;
1486 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1487 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1488 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1489 if (vertstring && vertstring[0])
1493 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1494 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1495 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1496 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1499 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1502 vsbinsize = vsbuffer->GetBufferSize();
1503 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1504 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1505 vsbuffer->Release();
1509 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1510 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1514 if (fragstring && fragstring[0])
1518 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1519 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1520 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1521 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1524 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1527 psbinsize = psbuffer->GetBufferSize();
1528 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1529 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1530 psbuffer->Release();
1534 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1535 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1539 Sys_UnloadLibrary(&d3dx9_dll);
1542 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1546 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1547 if (FAILED(vsresult))
1548 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1549 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1550 if (FAILED(psresult))
1551 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1553 // free the shader data
1554 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1555 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1558 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1561 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1562 int vertstring_length = 0;
1563 int geomstring_length = 0;
1564 int fragstring_length = 0;
1566 char *vertexstring, *geometrystring, *fragmentstring;
1567 char *vertstring, *geomstring, *fragstring;
1568 char permutationname[256];
1569 char cachename[256];
1570 int vertstrings_count = 0;
1571 int geomstrings_count = 0;
1572 int fragstrings_count = 0;
1573 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1574 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1575 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1580 p->vertexshader = NULL;
1581 p->pixelshader = NULL;
1583 permutationname[0] = 0;
1585 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1586 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1587 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1589 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1590 strlcat(cachename, "hlsl/", sizeof(cachename));
1592 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1593 vertstrings_count = 0;
1594 geomstrings_count = 0;
1595 fragstrings_count = 0;
1596 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1597 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1598 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1600 // the first pretext is which type of shader to compile as
1601 // (later these will all be bound together as a program object)
1602 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1603 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1604 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1606 // the second pretext is the mode (for example a light source)
1607 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1608 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1609 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1610 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1611 strlcat(cachename, modeinfo->name, sizeof(cachename));
1613 // now add all the permutation pretexts
1614 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1616 if (permutation & (1<<i))
1618 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1619 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1620 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1621 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1622 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1626 // keep line numbers correct
1627 vertstrings_list[vertstrings_count++] = "\n";
1628 geomstrings_list[geomstrings_count++] = "\n";
1629 fragstrings_list[fragstrings_count++] = "\n";
1634 R_CompileShader_AddStaticParms(mode, permutation);
1635 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1636 vertstrings_count += shaderstaticparms_count;
1637 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1638 geomstrings_count += shaderstaticparms_count;
1639 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1640 fragstrings_count += shaderstaticparms_count;
1642 // replace spaces in the cachename with _ characters
1643 for (i = 0;cachename[i];i++)
1644 if (cachename[i] == ' ')
1647 // now append the shader text itself
1648 vertstrings_list[vertstrings_count++] = vertexstring;
1649 geomstrings_list[geomstrings_count++] = geometrystring;
1650 fragstrings_list[fragstrings_count++] = fragmentstring;
1652 // if any sources were NULL, clear the respective list
1654 vertstrings_count = 0;
1655 if (!geometrystring)
1656 geomstrings_count = 0;
1657 if (!fragmentstring)
1658 fragstrings_count = 0;
1660 vertstring_length = 0;
1661 for (i = 0;i < vertstrings_count;i++)
1662 vertstring_length += strlen(vertstrings_list[i]);
1663 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1664 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1665 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1667 geomstring_length = 0;
1668 for (i = 0;i < geomstrings_count;i++)
1669 geomstring_length += strlen(geomstrings_list[i]);
1670 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1671 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1672 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1674 fragstring_length = 0;
1675 for (i = 0;i < fragstrings_count;i++)
1676 fragstring_length += strlen(fragstrings_list[i]);
1677 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1678 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1679 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1681 // try to load the cached shader, or generate one
1682 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1684 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1685 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1687 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1691 Mem_Free(vertstring);
1693 Mem_Free(geomstring);
1695 Mem_Free(fragstring);
1697 Mem_Free(vertexstring);
1699 Mem_Free(geometrystring);
1701 Mem_Free(fragmentstring);
1704 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1705 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1706 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);}
1707 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);}
1708 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);}
1709 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);}
1711 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1712 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1713 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);}
1714 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);}
1715 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);}
1716 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);}
1718 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1720 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1721 if (r_hlsl_permutation != perm)
1723 r_hlsl_permutation = perm;
1724 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1726 if (!r_hlsl_permutation->compiled)
1727 R_HLSL_CompilePermutation(perm, mode, permutation);
1728 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1730 // remove features until we find a valid permutation
1732 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1734 // reduce i more quickly whenever it would not remove any bits
1735 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1736 if (!(permutation & j))
1739 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1740 if (!r_hlsl_permutation->compiled)
1741 R_HLSL_CompilePermutation(perm, mode, permutation);
1742 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1745 if (i >= SHADERPERMUTATION_COUNT)
1747 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1748 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1749 return; // no bit left to clear, entire mode is broken
1753 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1754 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1756 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1757 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1758 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1762 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1764 DPSOFTRAST_SetShader(mode, permutation);
1765 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1766 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1767 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1770 void R_GLSL_Restart_f(void)
1772 unsigned int i, limit;
1773 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1774 Mem_Free(glslshaderstring);
1775 glslshaderstring = NULL;
1776 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1777 Mem_Free(hlslshaderstring);
1778 hlslshaderstring = NULL;
1779 switch(vid.renderpath)
1781 case RENDERPATH_D3D9:
1784 r_hlsl_permutation_t *p;
1785 r_hlsl_permutation = NULL;
1786 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1787 for (i = 0;i < limit;i++)
1789 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1791 if (p->vertexshader)
1792 IDirect3DVertexShader9_Release(p->vertexshader);
1794 IDirect3DPixelShader9_Release(p->pixelshader);
1795 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1798 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1802 case RENDERPATH_D3D10:
1803 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1805 case RENDERPATH_D3D11:
1806 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1808 case RENDERPATH_GL20:
1809 case RENDERPATH_GLES2:
1811 r_glsl_permutation_t *p;
1812 r_glsl_permutation = NULL;
1813 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1814 for (i = 0;i < limit;i++)
1816 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1818 GL_Backend_FreeProgram(p->program);
1819 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1822 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1825 case RENDERPATH_GL13:
1826 case RENDERPATH_GL11:
1828 case RENDERPATH_SOFT:
1833 void R_GLSL_DumpShader_f(void)
1838 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1841 FS_Print(file, "/* The engine may define the following macros:\n");
1842 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1843 for (i = 0;i < SHADERMODE_COUNT;i++)
1844 FS_Print(file, glslshadermodeinfo[i].pretext);
1845 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1846 FS_Print(file, shaderpermutationinfo[i].pretext);
1847 FS_Print(file, "*/\n");
1848 FS_Print(file, builtinshaderstring);
1850 Con_Printf("glsl/default.glsl written\n");
1853 Con_Printf("failed to write to glsl/default.glsl\n");
1855 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1858 FS_Print(file, "/* The engine may define the following macros:\n");
1859 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1860 for (i = 0;i < SHADERMODE_COUNT;i++)
1861 FS_Print(file, hlslshadermodeinfo[i].pretext);
1862 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1863 FS_Print(file, shaderpermutationinfo[i].pretext);
1864 FS_Print(file, "*/\n");
1865 FS_Print(file, builtinhlslshaderstring);
1867 Con_Printf("hlsl/default.hlsl written\n");
1870 Con_Printf("failed to write to hlsl/default.hlsl\n");
1873 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1876 texturemode = GL_MODULATE;
1877 switch (vid.renderpath)
1879 case RENDERPATH_D3D9:
1881 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))));
1882 R_Mesh_TexBind(GL20TU_FIRST , first );
1883 R_Mesh_TexBind(GL20TU_SECOND, second);
1886 case RENDERPATH_D3D10:
1887 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889 case RENDERPATH_D3D11:
1890 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892 case RENDERPATH_GL20:
1893 case RENDERPATH_GLES2:
1894 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))));
1895 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1896 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1898 case RENDERPATH_GL13:
1899 R_Mesh_TexBind(0, first );
1900 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1901 R_Mesh_TexBind(1, second);
1903 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1905 case RENDERPATH_GL11:
1906 R_Mesh_TexBind(0, first );
1908 case RENDERPATH_SOFT:
1909 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))));
1910 R_Mesh_TexBind(GL20TU_FIRST , first );
1911 R_Mesh_TexBind(GL20TU_SECOND, second);
1916 void R_SetupShader_DepthOrShadow(void)
1918 switch (vid.renderpath)
1920 case RENDERPATH_D3D9:
1922 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1925 case RENDERPATH_D3D10:
1926 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928 case RENDERPATH_D3D11:
1929 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931 case RENDERPATH_GL20:
1932 case RENDERPATH_GLES2:
1933 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1935 case RENDERPATH_GL13:
1936 R_Mesh_TexBind(0, 0);
1937 R_Mesh_TexBind(1, 0);
1939 case RENDERPATH_GL11:
1940 R_Mesh_TexBind(0, 0);
1942 case RENDERPATH_SOFT:
1943 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1948 void R_SetupShader_ShowDepth(void)
1950 switch (vid.renderpath)
1952 case RENDERPATH_D3D9:
1954 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1957 case RENDERPATH_D3D10:
1958 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960 case RENDERPATH_D3D11:
1961 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1963 case RENDERPATH_GL20:
1964 case RENDERPATH_GLES2:
1965 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1967 case RENDERPATH_GL13:
1969 case RENDERPATH_GL11:
1971 case RENDERPATH_SOFT:
1972 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1977 extern qboolean r_shadow_usingdeferredprepass;
1978 extern cvar_t r_shadow_deferred_8bitrange;
1979 extern rtexture_t *r_shadow_attenuationgradienttexture;
1980 extern rtexture_t *r_shadow_attenuation2dtexture;
1981 extern rtexture_t *r_shadow_attenuation3dtexture;
1982 extern qboolean r_shadow_usingshadowmap2d;
1983 extern qboolean r_shadow_usingshadowmaportho;
1984 extern float r_shadow_shadowmap_texturescale[2];
1985 extern float r_shadow_shadowmap_parameters[4];
1986 extern qboolean r_shadow_shadowmapvsdct;
1987 extern qboolean r_shadow_shadowmapsampler;
1988 extern int r_shadow_shadowmappcf;
1989 extern rtexture_t *r_shadow_shadowmap2dtexture;
1990 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1991 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1992 extern matrix4x4_t r_shadow_shadowmapmatrix;
1993 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1994 extern int r_shadow_prepass_width;
1995 extern int r_shadow_prepass_height;
1996 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1997 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1998 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1999 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2000 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2002 #define BLENDFUNC_ALLOWS_COLORMOD 1
2003 #define BLENDFUNC_ALLOWS_FOG 2
2004 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2005 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2006 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2007 static int R_BlendFuncFlags(int src, int dst)
2011 // a blendfunc allows colormod if:
2012 // a) it can never keep the destination pixel invariant, or
2013 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2014 // this is to prevent unintended side effects from colormod
2016 // a blendfunc allows fog if:
2017 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2018 // this is to prevent unintended side effects from fog
2020 // these checks are the output of fogeval.pl
2022 r |= BLENDFUNC_ALLOWS_COLORMOD;
2023 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2024 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2025 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2026 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2027 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2028 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2031 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2032 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2033 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2034 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2036 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2037 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2038 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2041 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2042 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2043 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2048 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)
2050 // select a permutation of the lighting shader appropriate to this
2051 // combination of texture, entity, light source, and fogging, only use the
2052 // minimum features necessary to avoid wasting rendering time in the
2053 // fragment shader on features that are not being used
2054 unsigned int permutation = 0;
2055 unsigned int mode = 0;
2057 static float dummy_colormod[3] = {1, 1, 1};
2058 float *colormod = rsurface.colormod;
2060 matrix4x4_t tempmatrix;
2061 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2062 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2063 permutation |= SHADERPERMUTATION_ALPHAKILL;
2064 if (rsurfacepass == RSURFPASS_BACKGROUND)
2066 // distorted background
2067 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2069 mode = SHADERMODE_WATER;
2070 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2071 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2072 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2074 // this is the right thing to do for wateralpha
2075 GL_BlendFunc(GL_ONE, GL_ZERO);
2076 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2080 // this is the right thing to do for entity alpha
2081 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2082 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2085 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2087 mode = SHADERMODE_REFRACTION;
2088 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2089 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2093 mode = SHADERMODE_GENERIC;
2094 permutation |= SHADERPERMUTATION_DIFFUSE;
2095 GL_BlendFunc(GL_ONE, GL_ZERO);
2096 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2099 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2101 if (r_glsl_offsetmapping.integer)
2103 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2104 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2105 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2106 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2107 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2109 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2110 if (r_glsl_offsetmapping_reliefmapping.integer)
2111 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2114 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2115 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2116 // normalmap (deferred prepass), may use alpha test on diffuse
2117 mode = SHADERMODE_DEFERREDGEOMETRY;
2118 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2119 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2120 GL_BlendFunc(GL_ONE, GL_ZERO);
2121 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2123 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2125 if (r_glsl_offsetmapping.integer)
2127 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2128 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2129 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2130 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2131 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2133 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2134 if (r_glsl_offsetmapping_reliefmapping.integer)
2135 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2138 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2139 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2141 mode = SHADERMODE_LIGHTSOURCE;
2142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2144 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2145 permutation |= SHADERPERMUTATION_CUBEFILTER;
2146 if (diffusescale > 0)
2147 permutation |= SHADERPERMUTATION_DIFFUSE;
2148 if (specularscale > 0)
2149 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2150 if (r_refdef.fogenabled)
2151 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2152 if (rsurface.texture->colormapping)
2153 permutation |= SHADERPERMUTATION_COLORMAPPING;
2154 if (r_shadow_usingshadowmap2d)
2156 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2157 if(r_shadow_shadowmapvsdct)
2158 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2160 if (r_shadow_shadowmapsampler)
2161 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2162 if (r_shadow_shadowmappcf > 1)
2163 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2164 else if (r_shadow_shadowmappcf)
2165 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2167 if (rsurface.texture->reflectmasktexture)
2168 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2170 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2172 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2174 if (r_glsl_offsetmapping.integer)
2176 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2177 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2178 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2179 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2180 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2182 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2183 if (r_glsl_offsetmapping_reliefmapping.integer)
2184 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2187 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2188 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2189 // unshaded geometry (fullbright or ambient model lighting)
2190 mode = SHADERMODE_FLATCOLOR;
2191 ambientscale = diffusescale = specularscale = 0;
2192 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2193 permutation |= SHADERPERMUTATION_GLOW;
2194 if (r_refdef.fogenabled)
2195 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2196 if (rsurface.texture->colormapping)
2197 permutation |= SHADERPERMUTATION_COLORMAPPING;
2198 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2200 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2201 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2203 if (r_shadow_shadowmapsampler)
2204 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2205 if (r_shadow_shadowmappcf > 1)
2206 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2207 else if (r_shadow_shadowmappcf)
2208 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2210 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2211 permutation |= SHADERPERMUTATION_REFLECTION;
2212 if (rsurface.texture->reflectmasktexture)
2213 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2214 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2215 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2217 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2219 if (r_glsl_offsetmapping.integer)
2221 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2222 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2223 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2224 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2225 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2227 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2228 if (r_glsl_offsetmapping_reliefmapping.integer)
2229 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2232 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2233 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2234 // directional model lighting
2235 mode = SHADERMODE_LIGHTDIRECTION;
2236 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2237 permutation |= SHADERPERMUTATION_GLOW;
2238 permutation |= SHADERPERMUTATION_DIFFUSE;
2239 if (specularscale > 0)
2240 permutation |= SHADERPERMUTATION_SPECULAR;
2241 if (r_refdef.fogenabled)
2242 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2243 if (rsurface.texture->colormapping)
2244 permutation |= SHADERPERMUTATION_COLORMAPPING;
2245 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2247 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2248 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2250 if (r_shadow_shadowmapsampler)
2251 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2252 if (r_shadow_shadowmappcf > 1)
2253 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2254 else if (r_shadow_shadowmappcf)
2255 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2257 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2258 permutation |= SHADERPERMUTATION_REFLECTION;
2259 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2260 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2261 if (rsurface.texture->reflectmasktexture)
2262 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2263 if (r_shadow_bouncegridtexture)
2264 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2265 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2266 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2268 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2270 if (r_glsl_offsetmapping.integer)
2272 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2273 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2274 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2275 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2276 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2278 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2279 if (r_glsl_offsetmapping_reliefmapping.integer)
2280 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2283 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2284 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2285 // ambient model lighting
2286 mode = SHADERMODE_LIGHTDIRECTION;
2287 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2288 permutation |= SHADERPERMUTATION_GLOW;
2289 if (r_refdef.fogenabled)
2290 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2291 if (rsurface.texture->colormapping)
2292 permutation |= SHADERPERMUTATION_COLORMAPPING;
2293 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2295 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2296 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2298 if (r_shadow_shadowmapsampler)
2299 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2300 if (r_shadow_shadowmappcf > 1)
2301 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2302 else if (r_shadow_shadowmappcf)
2303 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2305 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2306 permutation |= SHADERPERMUTATION_REFLECTION;
2307 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2308 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2309 if (rsurface.texture->reflectmasktexture)
2310 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2311 if (r_shadow_bouncegridtexture)
2312 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2313 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2314 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2318 if (r_glsl_offsetmapping.integer)
2320 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2321 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2322 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2323 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2324 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2326 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2327 if (r_glsl_offsetmapping_reliefmapping.integer)
2328 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2331 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2332 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2334 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2335 permutation |= SHADERPERMUTATION_GLOW;
2336 if (r_refdef.fogenabled)
2337 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2338 if (rsurface.texture->colormapping)
2339 permutation |= SHADERPERMUTATION_COLORMAPPING;
2340 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2342 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2343 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2345 if (r_shadow_shadowmapsampler)
2346 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2347 if (r_shadow_shadowmappcf > 1)
2348 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2349 else if (r_shadow_shadowmappcf)
2350 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2352 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2353 permutation |= SHADERPERMUTATION_REFLECTION;
2354 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2355 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2356 if (rsurface.texture->reflectmasktexture)
2357 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2358 if (FAKELIGHT_ENABLED)
2360 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2361 mode = SHADERMODE_FAKELIGHT;
2362 permutation |= SHADERPERMUTATION_DIFFUSE;
2363 if (specularscale > 0)
2364 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2366 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2368 // deluxemapping (light direction texture)
2369 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2370 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2372 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2373 permutation |= SHADERPERMUTATION_DIFFUSE;
2374 if (specularscale > 0)
2375 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2377 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2379 // fake deluxemapping (uniform light direction in tangentspace)
2380 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2381 permutation |= SHADERPERMUTATION_DIFFUSE;
2382 if (specularscale > 0)
2383 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2385 else if (rsurface.uselightmaptexture)
2387 // ordinary lightmapping (q1bsp, q3bsp)
2388 mode = SHADERMODE_LIGHTMAP;
2392 // ordinary vertex coloring (q3bsp)
2393 mode = SHADERMODE_VERTEXCOLOR;
2395 if (r_shadow_bouncegridtexture)
2396 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2397 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2398 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2400 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2401 colormod = dummy_colormod;
2402 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2403 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2404 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2405 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2406 switch(vid.renderpath)
2408 case RENDERPATH_D3D9:
2410 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);
2411 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2412 R_SetupShader_SetPermutationHLSL(mode, permutation);
2413 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2414 if (mode == SHADERMODE_LIGHTSOURCE)
2416 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2417 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2421 if (mode == SHADERMODE_LIGHTDIRECTION)
2423 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2426 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2427 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2428 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2429 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2430 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2432 if (mode == SHADERMODE_LIGHTSOURCE)
2434 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2435 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2436 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2437 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2438 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2440 // additive passes are only darkened by fog, not tinted
2441 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2442 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2446 if (mode == SHADERMODE_FLATCOLOR)
2448 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2450 else if (mode == SHADERMODE_LIGHTDIRECTION)
2452 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]);
2453 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2454 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);
2455 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);
2456 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2457 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2458 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2462 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2463 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2464 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);
2465 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);
2466 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2468 // additive passes are only darkened by fog, not tinted
2469 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2470 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2472 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2473 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);
2474 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2475 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2476 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2477 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2478 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2479 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2480 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2481 if (mode == SHADERMODE_WATER)
2482 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2484 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2485 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2487 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));
2488 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2489 if (rsurface.texture->pantstexture)
2490 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2492 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2493 if (rsurface.texture->shirttexture)
2494 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2496 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2497 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2498 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2499 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2500 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2501 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));
2502 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2503 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2505 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2506 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2507 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2508 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2509 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2510 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2511 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2512 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2513 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2514 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2515 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2516 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2517 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2518 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2519 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2520 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2521 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2522 if (rsurfacepass == RSURFPASS_BACKGROUND)
2524 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2525 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2526 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2530 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2532 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2533 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2534 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2535 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2536 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2538 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2539 if (rsurface.rtlight)
2541 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2542 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2547 case RENDERPATH_D3D10:
2548 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2550 case RENDERPATH_D3D11:
2551 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2553 case RENDERPATH_GL20:
2554 case RENDERPATH_GLES2:
2555 if (!vid.useinterleavedarrays)
2557 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);
2558 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2559 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2560 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2561 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2562 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2563 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2564 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2568 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);
2569 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2571 R_SetupShader_SetPermutationGLSL(mode, permutation);
2572 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2573 if (mode == SHADERMODE_LIGHTSOURCE)
2575 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2576 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2577 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2578 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2579 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2580 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);
2582 // additive passes are only darkened by fog, not tinted
2583 if (r_glsl_permutation->loc_FogColor >= 0)
2584 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2585 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2589 if (mode == SHADERMODE_FLATCOLOR)
2591 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2593 else if (mode == SHADERMODE_LIGHTDIRECTION)
2595 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]);
2596 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]);
2597 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);
2598 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);
2599 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);
2600 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]);
2601 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]);
2605 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]);
2606 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]);
2607 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);
2608 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);
2609 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);
2611 // additive passes are only darkened by fog, not tinted
2612 if (r_glsl_permutation->loc_FogColor >= 0)
2614 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2615 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2617 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2619 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);
2620 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]);
2621 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]);
2622 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]);
2623 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]);
2624 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2625 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2626 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2627 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]);
2629 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2630 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2631 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2632 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]);
2633 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]);
2635 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2636 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));
2637 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2638 if (r_glsl_permutation->loc_Color_Pants >= 0)
2640 if (rsurface.texture->pantstexture)
2641 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2643 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2645 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2647 if (rsurface.texture->shirttexture)
2648 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2650 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2652 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]);
2653 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2654 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2655 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2656 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));
2657 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]);
2658 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2659 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);}
2660 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2662 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2663 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2664 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2665 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2666 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2667 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2668 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2669 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2670 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2671 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2672 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2673 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2674 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2675 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2676 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);
2677 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2678 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2679 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2680 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2681 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2682 if (rsurfacepass == RSURFPASS_BACKGROUND)
2684 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);
2685 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);
2686 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);
2690 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);
2692 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2693 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2694 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2695 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2696 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2698 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2699 if (rsurface.rtlight)
2701 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2702 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2705 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2708 case RENDERPATH_GL13:
2709 case RENDERPATH_GL11:
2711 case RENDERPATH_SOFT:
2712 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);
2713 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2714 R_SetupShader_SetPermutationSoft(mode, permutation);
2715 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2716 if (mode == SHADERMODE_LIGHTSOURCE)
2718 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2719 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2720 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2721 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2722 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2723 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2725 // additive passes are only darkened by fog, not tinted
2726 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2727 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2731 if (mode == SHADERMODE_FLATCOLOR)
2733 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2735 else if (mode == SHADERMODE_LIGHTDIRECTION)
2737 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]);
2738 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2739 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);
2740 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);
2741 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2742 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]);
2743 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2747 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2748 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2749 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);
2750 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);
2751 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2753 // additive passes are only darkened by fog, not tinted
2754 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2757 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2758 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);
2759 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2760 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2761 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]);
2762 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]);
2763 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2764 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2765 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2766 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2768 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2769 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2770 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2771 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2772 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]);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2775 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));
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2777 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2779 if (rsurface.texture->pantstexture)
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2784 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2786 if (rsurface.texture->shirttexture)
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2791 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2792 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2793 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2795 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));
2796 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2797 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2799 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2800 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2801 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2802 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2803 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2804 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2805 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2806 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2807 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2808 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2809 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2810 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2811 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2812 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2813 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2814 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2815 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2816 if (rsurfacepass == RSURFPASS_BACKGROUND)
2818 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2819 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2820 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2824 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2826 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2827 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2828 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2829 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2830 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2832 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2833 if (rsurface.rtlight)
2835 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2836 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2843 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2845 // select a permutation of the lighting shader appropriate to this
2846 // combination of texture, entity, light source, and fogging, only use the
2847 // minimum features necessary to avoid wasting rendering time in the
2848 // fragment shader on features that are not being used
2849 unsigned int permutation = 0;
2850 unsigned int mode = 0;
2851 const float *lightcolorbase = rtlight->currentcolor;
2852 float ambientscale = rtlight->ambientscale;
2853 float diffusescale = rtlight->diffusescale;
2854 float specularscale = rtlight->specularscale;
2855 // this is the location of the light in view space
2856 vec3_t viewlightorigin;
2857 // this transforms from view space (camera) to light space (cubemap)
2858 matrix4x4_t viewtolight;
2859 matrix4x4_t lighttoview;
2860 float viewtolight16f[16];
2861 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2863 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2864 if (rtlight->currentcubemap != r_texture_whitecube)
2865 permutation |= SHADERPERMUTATION_CUBEFILTER;
2866 if (diffusescale > 0)
2867 permutation |= SHADERPERMUTATION_DIFFUSE;
2868 if (specularscale > 0)
2869 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2870 if (r_shadow_usingshadowmap2d)
2872 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2873 if (r_shadow_shadowmapvsdct)
2874 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2876 if (r_shadow_shadowmapsampler)
2877 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2878 if (r_shadow_shadowmappcf > 1)
2879 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2880 else if (r_shadow_shadowmappcf)
2881 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2883 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2884 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2885 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2886 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2887 switch(vid.renderpath)
2889 case RENDERPATH_D3D9:
2891 R_SetupShader_SetPermutationHLSL(mode, permutation);
2892 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2893 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2894 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2895 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2896 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2897 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2898 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2899 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2900 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2901 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2903 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2904 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2905 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2906 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2907 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2908 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2911 case RENDERPATH_D3D10:
2912 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2914 case RENDERPATH_D3D11:
2915 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2917 case RENDERPATH_GL20:
2918 case RENDERPATH_GLES2:
2919 R_SetupShader_SetPermutationGLSL(mode, permutation);
2920 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2921 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2922 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);
2923 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);
2924 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);
2925 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]);
2926 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]);
2927 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));
2928 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]);
2929 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2931 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2932 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2933 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2934 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2935 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2936 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2938 case RENDERPATH_GL13:
2939 case RENDERPATH_GL11:
2941 case RENDERPATH_SOFT:
2942 R_SetupShader_SetPermutationGLSL(mode, permutation);
2943 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2944 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2945 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2946 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2947 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2948 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2949 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]);
2950 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));
2951 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2952 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2954 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2955 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2956 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2957 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2958 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2959 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2964 #define SKINFRAME_HASH 1024
2968 int loadsequence; // incremented each level change
2969 memexpandablearray_t array;
2970 skinframe_t *hash[SKINFRAME_HASH];
2973 r_skinframe_t r_skinframe;
2975 void R_SkinFrame_PrepareForPurge(void)
2977 r_skinframe.loadsequence++;
2978 // wrap it without hitting zero
2979 if (r_skinframe.loadsequence >= 200)
2980 r_skinframe.loadsequence = 1;
2983 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2987 // mark the skinframe as used for the purging code
2988 skinframe->loadsequence = r_skinframe.loadsequence;
2991 void R_SkinFrame_Purge(void)
2995 for (i = 0;i < SKINFRAME_HASH;i++)
2997 for (s = r_skinframe.hash[i];s;s = s->next)
2999 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3001 if (s->merged == s->base)
3003 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3004 R_PurgeTexture(s->stain );s->stain = NULL;
3005 R_PurgeTexture(s->merged);s->merged = NULL;
3006 R_PurgeTexture(s->base );s->base = NULL;
3007 R_PurgeTexture(s->pants );s->pants = NULL;
3008 R_PurgeTexture(s->shirt );s->shirt = NULL;
3009 R_PurgeTexture(s->nmap );s->nmap = NULL;
3010 R_PurgeTexture(s->gloss );s->gloss = NULL;
3011 R_PurgeTexture(s->glow );s->glow = NULL;
3012 R_PurgeTexture(s->fog );s->fog = NULL;
3013 R_PurgeTexture(s->reflect);s->reflect = NULL;
3014 s->loadsequence = 0;
3020 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3022 char basename[MAX_QPATH];
3024 Image_StripImageExtension(name, basename, sizeof(basename));
3026 if( last == NULL ) {
3028 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3029 item = r_skinframe.hash[hashindex];
3034 // linearly search through the hash bucket
3035 for( ; item ; item = item->next ) {
3036 if( !strcmp( item->basename, basename ) ) {
3043 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3047 char basename[MAX_QPATH];
3049 Image_StripImageExtension(name, basename, sizeof(basename));
3051 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3052 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3053 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3057 rtexture_t *dyntexture;
3058 // check whether its a dynamic texture
3059 dyntexture = CL_GetDynTexture( basename );
3060 if (!add && !dyntexture)
3062 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3063 memset(item, 0, sizeof(*item));
3064 strlcpy(item->basename, basename, sizeof(item->basename));
3065 item->base = dyntexture; // either NULL or dyntexture handle
3066 item->textureflags = textureflags;
3067 item->comparewidth = comparewidth;
3068 item->compareheight = compareheight;
3069 item->comparecrc = comparecrc;
3070 item->next = r_skinframe.hash[hashindex];
3071 r_skinframe.hash[hashindex] = item;
3073 else if( item->base == NULL )
3075 rtexture_t *dyntexture;
3076 // check whether its a dynamic texture
3077 // 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]
3078 dyntexture = CL_GetDynTexture( basename );
3079 item->base = dyntexture; // either NULL or dyntexture handle
3082 R_SkinFrame_MarkUsed(item);
3086 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3088 unsigned long long avgcolor[5], wsum; \
3096 for(pix = 0; pix < cnt; ++pix) \
3099 for(comp = 0; comp < 3; ++comp) \
3101 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3104 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3106 for(comp = 0; comp < 3; ++comp) \
3107 avgcolor[comp] += getpixel * w; \
3110 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3111 avgcolor[4] += getpixel; \
3113 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3115 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3116 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3117 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3118 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3121 extern cvar_t gl_picmip;
3122 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3125 unsigned char *pixels;
3126 unsigned char *bumppixels;
3127 unsigned char *basepixels = NULL;
3128 int basepixels_width = 0;
3129 int basepixels_height = 0;
3130 skinframe_t *skinframe;
3131 rtexture_t *ddsbase = NULL;
3132 qboolean ddshasalpha = false;
3133 float ddsavgcolor[4];
3134 char basename[MAX_QPATH];
3135 int miplevel = R_PicmipForFlags(textureflags);
3136 int savemiplevel = miplevel;
3139 if (cls.state == ca_dedicated)
3142 // return an existing skinframe if already loaded
3143 // if loading of the first image fails, don't make a new skinframe as it
3144 // would cause all future lookups of this to be missing
3145 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3146 if (skinframe && skinframe->base)
3149 Image_StripImageExtension(name, basename, sizeof(basename));
3151 // check for DDS texture file first
3152 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3154 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3155 if (basepixels == NULL)
3159 // FIXME handle miplevel
3161 if (developer_loading.integer)
3162 Con_Printf("loading skin \"%s\"\n", name);
3164 // we've got some pixels to store, so really allocate this new texture now
3166 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3167 skinframe->stain = NULL;
3168 skinframe->merged = NULL;
3169 skinframe->base = NULL;
3170 skinframe->pants = NULL;
3171 skinframe->shirt = NULL;
3172 skinframe->nmap = NULL;
3173 skinframe->gloss = NULL;
3174 skinframe->glow = NULL;
3175 skinframe->fog = NULL;
3176 skinframe->reflect = NULL;
3177 skinframe->hasalpha = false;
3181 skinframe->base = ddsbase;
3182 skinframe->hasalpha = ddshasalpha;
3183 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3184 if (r_loadfog && skinframe->hasalpha)
3185 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3186 //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]);
3190 basepixels_width = image_width;
3191 basepixels_height = image_height;
3192 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);
3193 if (textureflags & TEXF_ALPHA)
3195 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3197 if (basepixels[j] < 255)
3199 skinframe->hasalpha = true;
3203 if (r_loadfog && skinframe->hasalpha)
3205 // has transparent pixels
3206 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3207 for (j = 0;j < image_width * image_height * 4;j += 4)
3212 pixels[j+3] = basepixels[j+3];
3214 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);
3218 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3219 //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]);
3220 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3221 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3222 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3223 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3228 mymiplevel = savemiplevel;
3229 if (r_loadnormalmap)
3230 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);
3231 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3233 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3234 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3235 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3236 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3239 // _norm is the name used by tenebrae and has been adopted as standard
3240 if (r_loadnormalmap && skinframe->nmap == NULL)
3242 mymiplevel = savemiplevel;
3243 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3245 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);
3249 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3251 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3252 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3253 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);
3255 Mem_Free(bumppixels);
3257 else if (r_shadow_bumpscale_basetexture.value > 0)
3259 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3260 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3261 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);
3264 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3265 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3268 // _luma is supported only for tenebrae compatibility
3269 // _glow is the preferred name
3270 mymiplevel = savemiplevel;
3271 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))))
3273 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);
3274 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3275 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3276 Mem_Free(pixels);pixels = NULL;
3279 mymiplevel = savemiplevel;
3280 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3282 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);
3283 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3284 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3289 mymiplevel = savemiplevel;
3290 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3292 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);
3293 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3294 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3299 mymiplevel = savemiplevel;
3300 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3302 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);
3303 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3304 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3309 mymiplevel = savemiplevel;
3310 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3312 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);
3313 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3314 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3320 Mem_Free(basepixels);
3325 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3326 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3329 unsigned char *temp1, *temp2;
3330 skinframe_t *skinframe;
3332 if (cls.state == ca_dedicated)
3335 // if already loaded just return it, otherwise make a new skinframe
3336 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3337 if (skinframe && skinframe->base)
3340 skinframe->stain = NULL;
3341 skinframe->merged = NULL;
3342 skinframe->base = NULL;
3343 skinframe->pants = NULL;
3344 skinframe->shirt = NULL;
3345 skinframe->nmap = NULL;
3346 skinframe->gloss = NULL;
3347 skinframe->glow = NULL;
3348 skinframe->fog = NULL;
3349 skinframe->reflect = NULL;
3350 skinframe->hasalpha = false;
3352 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3356 if (developer_loading.integer)
3357 Con_Printf("loading 32bit skin \"%s\"\n", name);
3359 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3361 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3362 temp2 = temp1 + width * height * 4;
3363 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3364 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);
3367 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3368 if (textureflags & TEXF_ALPHA)
3370 for (i = 3;i < width * height * 4;i += 4)
3372 if (skindata[i] < 255)
3374 skinframe->hasalpha = true;
3378 if (r_loadfog && skinframe->hasalpha)
3380 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3381 memcpy(fogpixels, skindata, width * height * 4);
3382 for (i = 0;i < width * height * 4;i += 4)
3383 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3384 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3385 Mem_Free(fogpixels);
3389 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3390 //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]);
3395 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3399 skinframe_t *skinframe;
3401 if (cls.state == ca_dedicated)
3404 // if already loaded just return it, otherwise make a new skinframe
3405 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3406 if (skinframe && skinframe->base)
3409 skinframe->stain = NULL;
3410 skinframe->merged = NULL;
3411 skinframe->base = NULL;
3412 skinframe->pants = NULL;
3413 skinframe->shirt = NULL;
3414 skinframe->nmap = NULL;
3415 skinframe->gloss = NULL;
3416 skinframe->glow = NULL;
3417 skinframe->fog = NULL;
3418 skinframe->reflect = NULL;
3419 skinframe->hasalpha = false;
3421 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3425 if (developer_loading.integer)
3426 Con_Printf("loading quake skin \"%s\"\n", name);
3428 // 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)
3429 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3430 memcpy(skinframe->qpixels, skindata, width*height);
3431 skinframe->qwidth = width;
3432 skinframe->qheight = height;
3435 for (i = 0;i < width * height;i++)
3436 featuresmask |= palette_featureflags[skindata[i]];
3438 skinframe->hasalpha = false;
3439 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3440 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3441 skinframe->qgeneratemerged = true;
3442 skinframe->qgeneratebase = skinframe->qhascolormapping;
3443 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3445 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3446 //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]);
3451 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3455 unsigned char *skindata;
3457 if (!skinframe->qpixels)
3460 if (!skinframe->qhascolormapping)
3461 colormapped = false;
3465 if (!skinframe->qgeneratebase)
3470 if (!skinframe->qgeneratemerged)
3474 width = skinframe->qwidth;
3475 height = skinframe->qheight;
3476 skindata = skinframe->qpixels;
3478 if (skinframe->qgeneratenmap)
3480 unsigned char *temp1, *temp2;
3481 skinframe->qgeneratenmap = false;
3482 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3483 temp2 = temp1 + width * height * 4;
3484 // use either a custom palette or the quake palette
3485 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3486 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3487 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);
3491 if (skinframe->qgenerateglow)
3493 skinframe->qgenerateglow = false;
3494 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3499 skinframe->qgeneratebase = false;
3500 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);
3501 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3502 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3506 skinframe->qgeneratemerged = false;
3507 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);
3510 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3512 Mem_Free(skinframe->qpixels);
3513 skinframe->qpixels = NULL;
3517 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)
3520 skinframe_t *skinframe;
3522 if (cls.state == ca_dedicated)
3525 // if already loaded just return it, otherwise make a new skinframe
3526 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3527 if (skinframe && skinframe->base)
3530 skinframe->stain = NULL;
3531 skinframe->merged = NULL;
3532 skinframe->base = NULL;
3533 skinframe->pants = NULL;
3534 skinframe->shirt = NULL;
3535 skinframe->nmap = NULL;
3536 skinframe->gloss = NULL;
3537 skinframe->glow = NULL;
3538 skinframe->fog = NULL;
3539 skinframe->reflect = NULL;
3540 skinframe->hasalpha = false;
3542 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3546 if (developer_loading.integer)
3547 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3549 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3550 if (textureflags & TEXF_ALPHA)
3552 for (i = 0;i < width * height;i++)
3554 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3556 skinframe->hasalpha = true;
3560 if (r_loadfog && skinframe->hasalpha)
3561 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3564 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3565 //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]);
3570 skinframe_t *R_SkinFrame_LoadMissing(void)
3572 skinframe_t *skinframe;
3574 if (cls.state == ca_dedicated)
3577 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3578 skinframe->stain = NULL;
3579 skinframe->merged = NULL;
3580 skinframe->base = NULL;
3581 skinframe->pants = NULL;
3582 skinframe->shirt = NULL;
3583 skinframe->nmap = NULL;
3584 skinframe->gloss = NULL;
3585 skinframe->glow = NULL;
3586 skinframe->fog = NULL;
3587 skinframe->reflect = NULL;
3588 skinframe->hasalpha = false;
3590 skinframe->avgcolor[0] = rand() / RAND_MAX;
3591 skinframe->avgcolor[1] = rand() / RAND_MAX;
3592 skinframe->avgcolor[2] = rand() / RAND_MAX;
3593 skinframe->avgcolor[3] = 1;
3598 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3599 typedef struct suffixinfo_s
3602 qboolean flipx, flipy, flipdiagonal;
3605 static suffixinfo_t suffix[3][6] =
3608 {"px", false, false, false},
3609 {"nx", false, false, false},
3610 {"py", false, false, false},
3611 {"ny", false, false, false},
3612 {"pz", false, false, false},
3613 {"nz", false, false, false}
3616 {"posx", false, false, false},
3617 {"negx", false, false, false},
3618 {"posy", false, false, false},
3619 {"negy", false, false, false},
3620 {"posz", false, false, false},
3621 {"negz", false, false, false}
3624 {"rt", true, false, true},
3625 {"lf", false, true, true},
3626 {"ft", true, true, false},
3627 {"bk", false, false, false},
3628 {"up", true, false, true},
3629 {"dn", true, false, true}
3633 static int componentorder[4] = {0, 1, 2, 3};
3635 rtexture_t *R_LoadCubemap(const char *basename)
3637 int i, j, cubemapsize;
3638 unsigned char *cubemappixels, *image_buffer;
3639 rtexture_t *cubemaptexture;
3641 // must start 0 so the first loadimagepixels has no requested width/height
3643 cubemappixels = NULL;
3644 cubemaptexture = NULL;
3645 // keep trying different suffix groups (posx, px, rt) until one loads
3646 for (j = 0;j < 3 && !cubemappixels;j++)
3648 // load the 6 images in the suffix group
3649 for (i = 0;i < 6;i++)
3651 // generate an image name based on the base and and suffix
3652 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3654 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3656 // an image loaded, make sure width and height are equal
3657 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3659 // if this is the first image to load successfully, allocate the cubemap memory
3660 if (!cubemappixels && image_width >= 1)
3662 cubemapsize = image_width;
3663 // note this clears to black, so unavailable sides are black
3664 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3666 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3668 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);
3671 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3673 Mem_Free(image_buffer);
3677 // if a cubemap loaded, upload it
3680 if (developer_loading.integer)
3681 Con_Printf("loading cubemap \"%s\"\n", basename);
3683 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3684 Mem_Free(cubemappixels);
3688 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3689 if (developer_loading.integer)
3691 Con_Printf("(tried tried images ");
3692 for (j = 0;j < 3;j++)
3693 for (i = 0;i < 6;i++)
3694 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3695 Con_Print(" and was unable to find any of them).\n");
3698 return cubemaptexture;
3701 rtexture_t *R_GetCubemap(const char *basename)
3704 for (i = 0;i < r_texture_numcubemaps;i++)
3705 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3706 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3707 if (i >= MAX_CUBEMAPS)
3708 return r_texture_whitecube;
3709 r_texture_numcubemaps++;
3710 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3711 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3712 return r_texture_cubemaps[i].texture;
3715 void R_FreeCubemaps(void)
3718 for (i = 0;i < r_texture_numcubemaps;i++)
3720 if (developer_loading.integer)
3721 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3722 if (r_texture_cubemaps[i].texture)
3723 R_FreeTexture(r_texture_cubemaps[i].texture);
3725 r_texture_numcubemaps = 0;
3728 void R_Main_FreeViewCache(void)
3730 if (r_refdef.viewcache.entityvisible)
3731 Mem_Free(r_refdef.viewcache.entityvisible);
3732 if (r_refdef.viewcache.world_pvsbits)
3733 Mem_Free(r_refdef.viewcache.world_pvsbits);
3734 if (r_refdef.viewcache.world_leafvisible)
3735 Mem_Free(r_refdef.viewcache.world_leafvisible);
3736 if (r_refdef.viewcache.world_surfacevisible)
3737 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3738 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3741 void R_Main_ResizeViewCache(void)
3743 int numentities = r_refdef.scene.numentities;
3744 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3745 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3746 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3747 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3748 if (r_refdef.viewcache.maxentities < numentities)
3750 r_refdef.viewcache.maxentities = numentities;
3751 if (r_refdef.viewcache.entityvisible)
3752 Mem_Free(r_refdef.viewcache.entityvisible);
3753 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3755 if (r_refdef.viewcache.world_numclusters != numclusters)
3757 r_refdef.viewcache.world_numclusters = numclusters;
3758 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3759 if (r_refdef.viewcache.world_pvsbits)
3760 Mem_Free(r_refdef.viewcache.world_pvsbits);
3761 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3763 if (r_refdef.viewcache.world_numleafs != numleafs)
3765 r_refdef.viewcache.world_numleafs = numleafs;
3766 if (r_refdef.viewcache.world_leafvisible)
3767 Mem_Free(r_refdef.viewcache.world_leafvisible);
3768 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3770 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3772 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3773 if (r_refdef.viewcache.world_surfacevisible)
3774 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3775 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3779 extern rtexture_t *loadingscreentexture;
3780 void gl_main_start(void)
3782 loadingscreentexture = NULL;
3783 r_texture_blanknormalmap = NULL;
3784 r_texture_white = NULL;
3785 r_texture_grey128 = NULL;
3786 r_texture_black = NULL;
3787 r_texture_whitecube = NULL;
3788 r_texture_normalizationcube = NULL;
3789 r_texture_fogattenuation = NULL;
3790 r_texture_fogheighttexture = NULL;
3791 r_texture_gammaramps = NULL;
3792 r_texture_numcubemaps = 0;
3794 r_loaddds = r_texture_dds_load.integer != 0;
3795 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3797 switch(vid.renderpath)
3799 case RENDERPATH_GL20:
3800 case RENDERPATH_D3D9:
3801 case RENDERPATH_D3D10:
3802 case RENDERPATH_D3D11:
3803 case RENDERPATH_SOFT:
3804 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3805 Cvar_SetValueQuick(&gl_combine, 1);
3806 Cvar_SetValueQuick(&r_glsl, 1);
3807 r_loadnormalmap = true;
3811 case RENDERPATH_GL13:
3812 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3813 Cvar_SetValueQuick(&gl_combine, 1);
3814 Cvar_SetValueQuick(&r_glsl, 0);
3815 r_loadnormalmap = false;
3816 r_loadgloss = false;
3819 case RENDERPATH_GL11:
3820 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3821 Cvar_SetValueQuick(&gl_combine, 0);
3822 Cvar_SetValueQuick(&r_glsl, 0);
3823 r_loadnormalmap = false;
3824 r_loadgloss = false;
3827 case RENDERPATH_GLES2:
3828 Cvar_SetValueQuick(&r_textureunits, 1);
3829 Cvar_SetValueQuick(&gl_combine, 1);
3830 Cvar_SetValueQuick(&r_glsl, 1);
3831 r_loadnormalmap = true;
3832 r_loadgloss = false;
3838 R_FrameData_Reset();
3842 memset(r_queries, 0, sizeof(r_queries));
3844 r_qwskincache = NULL;
3845 r_qwskincache_size = 0;
3847 // set up r_skinframe loading system for textures
3848 memset(&r_skinframe, 0, sizeof(r_skinframe));
3849 r_skinframe.loadsequence = 1;
3850 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3852 r_main_texturepool = R_AllocTexturePool();
3853 R_BuildBlankTextures();
3855 if (vid.support.arb_texture_cube_map)
3858 R_BuildNormalizationCube();
3860 r_texture_fogattenuation = NULL;
3861 r_texture_fogheighttexture = NULL;
3862 r_texture_gammaramps = NULL;
3863 //r_texture_fogintensity = NULL;
3864 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3865 memset(&r_waterstate, 0, sizeof(r_waterstate));
3866 r_glsl_permutation = NULL;
3867 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3868 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3869 glslshaderstring = NULL;
3871 r_hlsl_permutation = NULL;
3872 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3873 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3875 hlslshaderstring = NULL;
3876 memset(&r_svbsp, 0, sizeof (r_svbsp));
3878 r_refdef.fogmasktable_density = 0;
3881 void gl_main_shutdown(void)
3884 R_FrameData_Reset();
3886 R_Main_FreeViewCache();
3888 switch(vid.renderpath)
3890 case RENDERPATH_GL11:
3891 case RENDERPATH_GL13:
3892 case RENDERPATH_GL20:
3893 case RENDERPATH_GLES2:
3895 qglDeleteQueriesARB(r_maxqueries, r_queries);
3897 case RENDERPATH_D3D9:
3898 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3900 case RENDERPATH_D3D10:
3901 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3903 case RENDERPATH_D3D11:
3904 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3906 case RENDERPATH_SOFT:
3912 memset(r_queries, 0, sizeof(r_queries));
3914 r_qwskincache = NULL;
3915 r_qwskincache_size = 0;
3917 // clear out the r_skinframe state
3918 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3919 memset(&r_skinframe, 0, sizeof(r_skinframe));
3922 Mem_Free(r_svbsp.nodes);
3923 memset(&r_svbsp, 0, sizeof (r_svbsp));
3924 R_FreeTexturePool(&r_main_texturepool);
3925 loadingscreentexture = NULL;
3926 r_texture_blanknormalmap = NULL;
3927 r_texture_white = NULL;
3928 r_texture_grey128 = NULL;
3929 r_texture_black = NULL;
3930 r_texture_whitecube = NULL;
3931 r_texture_normalizationcube = NULL;
3932 r_texture_fogattenuation = NULL;
3933 r_texture_fogheighttexture = NULL;
3934 r_texture_gammaramps = NULL;
3935 r_texture_numcubemaps = 0;
3936 //r_texture_fogintensity = NULL;
3937 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3938 memset(&r_waterstate, 0, sizeof(r_waterstate));
3941 r_glsl_permutation = NULL;
3942 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3943 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3944 glslshaderstring = NULL;
3946 r_hlsl_permutation = NULL;
3947 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3948 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3950 hlslshaderstring = NULL;
3953 extern void CL_ParseEntityLump(char *entitystring);
3954 void gl_main_newmap(void)
3956 // FIXME: move this code to client
3957 char *entities, entname[MAX_QPATH];
3959 Mem_Free(r_qwskincache);
3960 r_qwskincache = NULL;
3961 r_qwskincache_size = 0;
3964 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3965 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3967 CL_ParseEntityLump(entities);
3971 if (cl.worldmodel->brush.entities)
3972 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3974 R_Main_FreeViewCache();
3976 R_FrameData_Reset();
3979 void GL_Main_Init(void)
3981 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3983 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3984 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3985 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3986 if (gamemode == GAME_NEHAHRA)
3988 Cvar_RegisterVariable (&gl_fogenable);
3989 Cvar_RegisterVariable (&gl_fogdensity);
3990 Cvar_RegisterVariable (&gl_fogred);
3991 Cvar_RegisterVariable (&gl_foggreen);
3992 Cvar_RegisterVariable (&gl_fogblue);
3993 Cvar_RegisterVariable (&gl_fogstart);
3994 Cvar_RegisterVariable (&gl_fogend);
3995 Cvar_RegisterVariable (&gl_skyclip);
3997 Cvar_RegisterVariable(&r_motionblur);
3998 Cvar_RegisterVariable(&r_motionblur_maxblur);
3999 Cvar_RegisterVariable(&r_motionblur_bmin);
4000 Cvar_RegisterVariable(&r_motionblur_vmin);
4001 Cvar_RegisterVariable(&r_motionblur_vmax);
4002 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4003 Cvar_RegisterVariable(&r_motionblur_randomize);
4004 Cvar_RegisterVariable(&r_damageblur);
4005 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4006 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4007 Cvar_RegisterVariable(&r_equalize_entities_by);
4008 Cvar_RegisterVariable(&r_equalize_entities_to);
4009 Cvar_RegisterVariable(&r_depthfirst);
4010 Cvar_RegisterVariable(&r_useinfinitefarclip);
4011 Cvar_RegisterVariable(&r_farclip_base);
4012 Cvar_RegisterVariable(&r_farclip_world);
4013 Cvar_RegisterVariable(&r_nearclip);
4014 Cvar_RegisterVariable(&r_showbboxes);
4015 Cvar_RegisterVariable(&r_showsurfaces);
4016 Cvar_RegisterVariable(&r_showtris);
4017 Cvar_RegisterVariable(&r_shownormals);
4018 Cvar_RegisterVariable(&r_showlighting);
4019 Cvar_RegisterVariable(&r_showshadowvolumes);
4020 Cvar_RegisterVariable(&r_showcollisionbrushes);
4021 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4022 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4023 Cvar_RegisterVariable(&r_showdisabledepthtest);
4024 Cvar_RegisterVariable(&r_drawportals);
4025 Cvar_RegisterVariable(&r_drawentities);
4026 Cvar_RegisterVariable(&r_draw2d);
4027 Cvar_RegisterVariable(&r_drawworld);
4028 Cvar_RegisterVariable(&r_cullentities_trace);
4029 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4030 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4031 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4032 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4033 Cvar_RegisterVariable(&r_drawviewmodel);
4034 Cvar_RegisterVariable(&r_drawexteriormodel);
4035 Cvar_RegisterVariable(&r_speeds);
4036 Cvar_RegisterVariable(&r_fullbrights);
4037 Cvar_RegisterVariable(&r_wateralpha);
4038 Cvar_RegisterVariable(&r_dynamic);
4039 Cvar_RegisterVariable(&r_fakelight);
4040 Cvar_RegisterVariable(&r_fakelight_intensity);
4041 Cvar_RegisterVariable(&r_fullbright);
4042 Cvar_RegisterVariable(&r_shadows);
4043 Cvar_RegisterVariable(&r_shadows_darken);
4044 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4045 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4046 Cvar_RegisterVariable(&r_shadows_throwdistance);
4047 Cvar_RegisterVariable(&r_shadows_throwdirection);
4048 Cvar_RegisterVariable(&r_shadows_focus);
4049 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4050 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4051 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4052 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4053 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4054 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4055 Cvar_RegisterVariable(&r_fog_exp2);
4056 Cvar_RegisterVariable(&r_drawfog);
4057 Cvar_RegisterVariable(&r_transparentdepthmasking);
4058 Cvar_RegisterVariable(&r_texture_dds_load);
4059 Cvar_RegisterVariable(&r_texture_dds_save);
4060 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4061 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4062 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4063 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4064 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4065 Cvar_RegisterVariable(&r_textureunits);
4066 Cvar_RegisterVariable(&gl_combine);
4067 Cvar_RegisterVariable(&r_glsl);
4068 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4069 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4070 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4071 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4072 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4073 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4074 Cvar_RegisterVariable(&r_glsl_postprocess);
4075 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4076 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4077 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4078 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4079 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4080 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4081 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4082 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4084 Cvar_RegisterVariable(&r_water);
4085 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4086 Cvar_RegisterVariable(&r_water_clippingplanebias);
4087 Cvar_RegisterVariable(&r_water_refractdistort);
4088 Cvar_RegisterVariable(&r_water_reflectdistort);
4089 Cvar_RegisterVariable(&r_water_scissormode);
4090 Cvar_RegisterVariable(&r_lerpsprites);
4091 Cvar_RegisterVariable(&r_lerpmodels);
4092 Cvar_RegisterVariable(&r_lerplightstyles);
4093 Cvar_RegisterVariable(&r_waterscroll);
4094 Cvar_RegisterVariable(&r_bloom);
4095 Cvar_RegisterVariable(&r_bloom_colorscale);
4096 Cvar_RegisterVariable(&r_bloom_brighten);
4097 Cvar_RegisterVariable(&r_bloom_blur);
4098 Cvar_RegisterVariable(&r_bloom_resolution);
4099 Cvar_RegisterVariable(&r_bloom_colorexponent);
4100 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4101 Cvar_RegisterVariable(&r_hdr);
4102 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4103 Cvar_RegisterVariable(&r_hdr_glowintensity);
4104 Cvar_RegisterVariable(&r_hdr_range);
4105 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4106 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4107 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4108 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4109 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4110 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4111 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4112 Cvar_RegisterVariable(&developer_texturelogging);
4113 Cvar_RegisterVariable(&gl_lightmaps);
4114 Cvar_RegisterVariable(&r_test);
4115 Cvar_RegisterVariable(&r_glsl_saturation);
4116 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4117 Cvar_RegisterVariable(&r_framedatasize);
4118 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4119 Cvar_SetValue("r_fullbrights", 0);
4120 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4122 Cvar_RegisterVariable(&r_track_sprites);
4123 Cvar_RegisterVariable(&r_track_sprites_flags);
4124 Cvar_RegisterVariable(&r_track_sprites_scalew);
4125 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4126 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4127 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4128 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4129 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4132 extern void R_Textures_Init(void);
4133 extern void GL_Draw_Init(void);
4134 extern void GL_Main_Init(void);
4135 extern void R_Shadow_Init(void);
4136 extern void R_Sky_Init(void);
4137 extern void GL_Surf_Init(void);
4138 extern void R_Particles_Init(void);
4139 extern void R_Explosion_Init(void);
4140 extern void gl_backend_init(void);
4141 extern void Sbar_Init(void);
4142 extern void R_LightningBeams_Init(void);
4143 extern void Mod_RenderInit(void);
4144 extern void Font_Init(void);
4146 void Render_Init(void)
4159 R_LightningBeams_Init();
4168 extern char *ENGINE_EXTENSIONS;
4171 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4172 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4173 gl_version = (const char *)qglGetString(GL_VERSION);
4174 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4178 if (!gl_platformextensions)
4179 gl_platformextensions = "";
4181 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4182 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4183 Con_Printf("GL_VERSION: %s\n", gl_version);
4184 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4185 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4187 VID_CheckExtensions();
4189 // LordHavoc: report supported extensions
4190 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4192 // clear to black (loading plaque will be seen over this)
4193 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4196 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4200 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4202 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4205 p = r_refdef.view.frustum + i;
4210 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4214 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4218 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4222 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4226 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4230 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4234 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4238 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4246 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4250 for (i = 0;i < numplanes;i++)
4257 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4261 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4265 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4269 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4273 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4277 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4281 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4285 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4293 //==================================================================================
4295 // LordHavoc: this stores temporary data used within the same frame
4297 typedef struct r_framedata_mem_s
4299 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4300 size_t size; // how much usable space
4301 size_t current; // how much space in use
4302 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4303 size_t wantedsize; // how much space was allocated
4304 unsigned char *data; // start of real data (16byte aligned)
4308 static r_framedata_mem_t *r_framedata_mem;
4310 void R_FrameData_Reset(void)
4312 while (r_framedata_mem)
4314 r_framedata_mem_t *next = r_framedata_mem->purge;
4315 Mem_Free(r_framedata_mem);
4316 r_framedata_mem = next;
4320 void R_FrameData_Resize(void)
4323 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4324 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4325 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4327 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4328 newmem->wantedsize = wantedsize;
4329 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4330 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4331 newmem->current = 0;
4333 newmem->purge = r_framedata_mem;
4334 r_framedata_mem = newmem;
4338 void R_FrameData_NewFrame(void)
4340 R_FrameData_Resize();
4341 if (!r_framedata_mem)
4343 // if we ran out of space on the last frame, free the old memory now
4344 while (r_framedata_mem->purge)
4346 // repeatedly remove the second item in the list, leaving only head
4347 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4348 Mem_Free(r_framedata_mem->purge);
4349 r_framedata_mem->purge = next;
4351 // reset the current mem pointer
4352 r_framedata_mem->current = 0;
4353 r_framedata_mem->mark = 0;
4356 void *R_FrameData_Alloc(size_t size)
4360 // align to 16 byte boundary - the data pointer is already aligned, so we
4361 // only need to ensure the size of every allocation is also aligned
4362 size = (size + 15) & ~15;
4364 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4366 // emergency - we ran out of space, allocate more memory
4367 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4368 R_FrameData_Resize();
4371 data = r_framedata_mem->data + r_framedata_mem->current;
4372 r_framedata_mem->current += size;
4374 // count the usage for stats
4375 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4376 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4378 return (void *)data;
4381 void *R_FrameData_Store(size_t size, void *data)
4383 void *d = R_FrameData_Alloc(size);
4385 memcpy(d, data, size);
4389 void R_FrameData_SetMark(void)
4391 if (!r_framedata_mem)
4393 r_framedata_mem->mark = r_framedata_mem->current;
4396 void R_FrameData_ReturnToMark(void)
4398 if (!r_framedata_mem)
4400 r_framedata_mem->current = r_framedata_mem->mark;
4403 //==================================================================================
4405 // LordHavoc: animcache originally written by Echon, rewritten since then
4408 * Animation cache prevents re-generating mesh data for an animated model
4409 * multiple times in one frame for lighting, shadowing, reflections, etc.
4412 void R_AnimCache_Free(void)
4416 void R_AnimCache_ClearCache(void)
4419 entity_render_t *ent;
4421 for (i = 0;i < r_refdef.scene.numentities;i++)
4423 ent = r_refdef.scene.entities[i];
4424 ent->animcache_vertex3f = NULL;
4425 ent->animcache_normal3f = NULL;
4426 ent->animcache_svector3f = NULL;
4427 ent->animcache_tvector3f = NULL;
4428 ent->animcache_vertexmesh = NULL;
4429 ent->animcache_vertex3fbuffer = NULL;
4430 ent->animcache_vertexmeshbuffer = NULL;
4434 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4438 // check if we need the meshbuffers
4439 if (!vid.useinterleavedarrays)
4442 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4443 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4444 // TODO: upload vertex3f buffer?
4445 if (ent->animcache_vertexmesh)
4447 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4448 for (i = 0;i < numvertices;i++)
4449 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4450 if (ent->animcache_svector3f)
4451 for (i = 0;i < numvertices;i++)
4452 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4453 if (ent->animcache_tvector3f)
4454 for (i = 0;i < numvertices;i++)
4455 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4456 if (ent->animcache_normal3f)
4457 for (i = 0;i < numvertices;i++)
4458 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4459 // TODO: upload vertexmeshbuffer?
4463 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4465 dp_model_t *model = ent->model;
4467 // see if it's already cached this frame
4468 if (ent->animcache_vertex3f)
4470 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4471 if (wantnormals || wanttangents)
4473 if (ent->animcache_normal3f)
4474 wantnormals = false;
4475 if (ent->animcache_svector3f)
4476 wanttangents = false;
4477 if (wantnormals || wanttangents)
4479 numvertices = model->surfmesh.num_vertices;
4481 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4484 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4485 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4487 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4488 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4494 // see if this ent is worth caching
4495 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4497 // get some memory for this entity and generate mesh data
4498 numvertices = model->surfmesh.num_vertices;
4499 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4501 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4504 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4505 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4507 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4508 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4513 void R_AnimCache_CacheVisibleEntities(void)
4516 qboolean wantnormals = true;
4517 qboolean wanttangents = !r_showsurfaces.integer;
4519 switch(vid.renderpath)
4521 case RENDERPATH_GL20:
4522 case RENDERPATH_D3D9:
4523 case RENDERPATH_D3D10:
4524 case RENDERPATH_D3D11:
4525 case RENDERPATH_GLES2:
4527 case RENDERPATH_GL13:
4528 case RENDERPATH_GL11:
4529 wanttangents = false;
4531 case RENDERPATH_SOFT:
4535 if (r_shownormals.integer)
4536 wanttangents = wantnormals = true;
4538 // TODO: thread this
4539 // NOTE: R_PrepareRTLights() also caches entities
4541 for (i = 0;i < r_refdef.scene.numentities;i++)
4542 if (r_refdef.viewcache.entityvisible[i])
4543 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4546 //==================================================================================
4548 static void R_View_UpdateEntityLighting (void)
4551 entity_render_t *ent;
4552 vec3_t tempdiffusenormal, avg;
4553 vec_t f, fa, fd, fdd;
4554 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4556 for (i = 0;i < r_refdef.scene.numentities;i++)
4558 ent = r_refdef.scene.entities[i];
4560 // skip unseen models
4561 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4565 if (ent->model && ent->model->brush.num_leafs)
4567 // TODO: use modellight for r_ambient settings on world?
4568 VectorSet(ent->modellight_ambient, 0, 0, 0);
4569 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4570 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4574 // fetch the lighting from the worldmodel data
4575 VectorClear(ent->modellight_ambient);
4576 VectorClear(ent->modellight_diffuse);
4577 VectorClear(tempdiffusenormal);
4578 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4581 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4583 // complete lightning for lit sprites
4584 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4585 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4587 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4588 org[2] = org[2] + r_overheadsprites_pushback.value;
4589 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4592 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4594 if(ent->flags & RENDER_EQUALIZE)
4596 // first fix up ambient lighting...
4597 if(r_equalize_entities_minambient.value > 0)
4599 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4602 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4603 if(fa < r_equalize_entities_minambient.value * fd)
4606 // fa'/fd' = minambient
4607 // fa'+0.25*fd' = fa+0.25*fd
4609 // fa' = fd' * minambient
4610 // fd'*(0.25+minambient) = fa+0.25*fd
4612 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4613 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4615 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4616 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
4617 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4618 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4623 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4625 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4626 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4630 // adjust brightness and saturation to target
4631 avg[0] = avg[1] = avg[2] = fa / f;
4632 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4633 avg[0] = avg[1] = avg[2] = fd / f;
4634 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4640 VectorSet(ent->modellight_ambient, 1, 1, 1);
4642 // move the light direction into modelspace coordinates for lighting code
4643 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4644 if(VectorLength2(ent->modellight_lightdir) == 0)
4645 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4646 VectorNormalize(ent->modellight_lightdir);
4650 #define MAX_LINEOFSIGHTTRACES 64
4652 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4655 vec3_t boxmins, boxmaxs;
4658 dp_model_t *model = r_refdef.scene.worldmodel;
4660 if (!model || !model->brush.TraceLineOfSight)
4663 // expand the box a little
4664 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4665 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4666 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4667 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4668 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4669 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4671 // return true if eye is inside enlarged box
4672 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4676 VectorCopy(eye, start);
4677 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4678 if (model->brush.TraceLineOfSight(model, start, end))
4681 // try various random positions
4682 for (i = 0;i < numsamples;i++)
4684 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4685 if (model->brush.TraceLineOfSight(model, start, end))
4693 static void R_View_UpdateEntityVisible (void)
4698 entity_render_t *ent;
4700 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4701 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4702 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4703 : RENDER_EXTERIORMODEL;
4704 if (!r_drawviewmodel.integer)
4705 renderimask |= RENDER_VIEWMODEL;
4706 if (!r_drawexteriormodel.integer)
4707 renderimask |= RENDER_EXTERIORMODEL;
4708 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4710 // worldmodel can check visibility
4711 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4712 for (i = 0;i < r_refdef.scene.numentities;i++)
4714 ent = r_refdef.scene.entities[i];
4715 if (!(ent->flags & renderimask))
4716 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)))
4717 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))
4718 r_refdef.viewcache.entityvisible[i] = true;
4720 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4721 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4723 for (i = 0;i < r_refdef.scene.numentities;i++)
4725 ent = r_refdef.scene.entities[i];
4726 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4728 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4730 continue; // temp entities do pvs only
4731 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4732 ent->last_trace_visibility = realtime;
4733 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4734 r_refdef.viewcache.entityvisible[i] = 0;
4741 // no worldmodel or it can't check visibility
4742 for (i = 0;i < r_refdef.scene.numentities;i++)
4744 ent = r_refdef.scene.entities[i];
4745 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));
4750 /// only used if skyrendermasked, and normally returns false
4751 int R_DrawBrushModelsSky (void)
4754 entity_render_t *ent;
4757 for (i = 0;i < r_refdef.scene.numentities;i++)
4759 if (!r_refdef.viewcache.entityvisible[i])
4761 ent = r_refdef.scene.entities[i];
4762 if (!ent->model || !ent->model->DrawSky)
4764 ent->model->DrawSky(ent);
4770 static void R_DrawNoModel(entity_render_t *ent);
4771 static void R_DrawModels(void)
4774 entity_render_t *ent;
4776 for (i = 0;i < r_refdef.scene.numentities;i++)
4778 if (!r_refdef.viewcache.entityvisible[i])
4780 ent = r_refdef.scene.entities[i];
4781 r_refdef.stats.entities++;
4782 if (ent->model && ent->model->Draw != NULL)
4783 ent->model->Draw(ent);
4789 static void R_DrawModelsDepth(void)
4792 entity_render_t *ent;
4794 for (i = 0;i < r_refdef.scene.numentities;i++)
4796 if (!r_refdef.viewcache.entityvisible[i])
4798 ent = r_refdef.scene.entities[i];
4799 if (ent->model && ent->model->DrawDepth != NULL)
4800 ent->model->DrawDepth(ent);
4804 static void R_DrawModelsDebug(void)
4807 entity_render_t *ent;
4809 for (i = 0;i < r_refdef.scene.numentities;i++)
4811 if (!r_refdef.viewcache.entityvisible[i])
4813 ent = r_refdef.scene.entities[i];
4814 if (ent->model && ent->model->DrawDebug != NULL)
4815 ent->model->DrawDebug(ent);
4819 static void R_DrawModelsAddWaterPlanes(void)
4822 entity_render_t *ent;
4824 for (i = 0;i < r_refdef.scene.numentities;i++)
4826 if (!r_refdef.viewcache.entityvisible[i])
4828 ent = r_refdef.scene.entities[i];
4829 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4830 ent->model->DrawAddWaterPlanes(ent);
4834 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4836 if (r_hdr_irisadaptation.integer)
4840 vec3_t diffusenormal;
4845 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4846 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4847 brightness = max(0.0000001f, brightness);
4848 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4849 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4850 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4851 current = r_hdr_irisadaptation_value.value;
4853 current = min(current + adjust, goal);
4854 else if (current > goal)
4855 current = max(current - adjust, goal);
4856 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4857 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4859 else if (r_hdr_irisadaptation_value.value != 1.0f)
4860 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4863 static void R_View_SetFrustum(const int *scissor)
4866 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4867 vec3_t forward, left, up, origin, v;
4871 // flipped x coordinates (because x points left here)
4872 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4873 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4875 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4876 switch(vid.renderpath)
4878 case RENDERPATH_D3D9:
4879 case RENDERPATH_D3D10:
4880 case RENDERPATH_D3D11:
4881 case RENDERPATH_SOFT:
4882 // non-flipped y coordinates
4883 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4884 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4886 case RENDERPATH_GL11:
4887 case RENDERPATH_GL13:
4888 case RENDERPATH_GL20:
4889 case RENDERPATH_GLES2:
4890 // non-flipped y coordinates
4891 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4892 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4897 // we can't trust r_refdef.view.forward and friends in reflected scenes
4898 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4901 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4902 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4903 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4904 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4905 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4906 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4907 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4908 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4909 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4910 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4911 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4912 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4916 zNear = r_refdef.nearclip;
4917 nudge = 1.0 - 1.0 / (1<<23);
4918 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4919 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4920 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4921 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4922 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4923 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4924 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4925 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4931 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4932 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4933 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4934 r_refdef.view.frustum[0].dist = m[15] - m[12];
4936 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4937 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4938 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4939 r_refdef.view.frustum[1].dist = m[15] + m[12];
4941 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4942 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4943 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4944 r_refdef.view.frustum[2].dist = m[15] - m[13];
4946 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4947 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4948 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4949 r_refdef.view.frustum[3].dist = m[15] + m[13];
4951 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4952 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4953 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4954 r_refdef.view.frustum[4].dist = m[15] - m[14];
4956 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4957 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4958 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4959 r_refdef.view.frustum[5].dist = m[15] + m[14];
4962 if (r_refdef.view.useperspective)
4964 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4965 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]);
4966 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]);
4967 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]);
4968 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]);
4970 // then the normals from the corners relative to origin
4971 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4972 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4973 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4974 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4976 // in a NORMAL view, forward cross left == up
4977 // in a REFLECTED view, forward cross left == down
4978 // so our cross products above need to be adjusted for a left handed coordinate system
4979 CrossProduct(forward, left, v);
4980 if(DotProduct(v, up) < 0)
4982 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4983 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4984 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4985 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4988 // Leaving those out was a mistake, those were in the old code, and they
4989 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4990 // I couldn't reproduce it after adding those normalizations. --blub
4991 VectorNormalize(r_refdef.view.frustum[0].normal);
4992 VectorNormalize(r_refdef.view.frustum[1].normal);
4993 VectorNormalize(r_refdef.view.frustum[2].normal);
4994 VectorNormalize(r_refdef.view.frustum[3].normal);
4996 // make the corners absolute
4997 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4998 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4999 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5000 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5003 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5005 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5006 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5007 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5008 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5009 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5013 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5014 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5015 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5016 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5017 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5018 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5019 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5020 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5021 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5022 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5024 r_refdef.view.numfrustumplanes = 5;
5026 if (r_refdef.view.useclipplane)
5028 r_refdef.view.numfrustumplanes = 6;
5029 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5032 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5033 PlaneClassify(r_refdef.view.frustum + i);
5035 // LordHavoc: note to all quake engine coders, Quake had a special case
5036 // for 90 degrees which assumed a square view (wrong), so I removed it,
5037 // Quake2 has it disabled as well.
5039 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5040 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5041 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5042 //PlaneClassify(&frustum[0]);
5044 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5045 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5046 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5047 //PlaneClassify(&frustum[1]);
5049 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5050 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5051 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5052 //PlaneClassify(&frustum[2]);
5054 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5055 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5056 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5057 //PlaneClassify(&frustum[3]);
5060 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5061 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5062 //PlaneClassify(&frustum[4]);
5065 void R_View_UpdateWithScissor(const int *myscissor)
5067 R_Main_ResizeViewCache();
5068 R_View_SetFrustum(myscissor);
5069 R_View_WorldVisibility(r_refdef.view.useclipplane);
5070 R_View_UpdateEntityVisible();
5071 R_View_UpdateEntityLighting();
5074 void R_View_Update(void)
5076 R_Main_ResizeViewCache();
5077 R_View_SetFrustum(NULL);
5078 R_View_WorldVisibility(r_refdef.view.useclipplane);
5079 R_View_UpdateEntityVisible();
5080 R_View_UpdateEntityLighting();
5083 void R_SetupView(qboolean allowwaterclippingplane)
5085 const float *customclipplane = NULL;
5087 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5089 // LordHavoc: couldn't figure out how to make this approach the
5090 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5091 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5092 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5093 dist = r_refdef.view.clipplane.dist;
5094 plane[0] = r_refdef.view.clipplane.normal[0];
5095 plane[1] = r_refdef.view.clipplane.normal[1];
5096 plane[2] = r_refdef.view.clipplane.normal[2];
5098 customclipplane = plane;
5101 if (!r_refdef.view.useperspective)
5102 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);
5103 else if (vid.stencil && r_useinfinitefarclip.integer)
5104 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);
5106 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);
5107 R_SetViewport(&r_refdef.view.viewport);
5110 void R_EntityMatrix(const matrix4x4_t *matrix)
5112 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5114 gl_modelmatrixchanged = false;
5115 gl_modelmatrix = *matrix;
5116 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5117 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5118 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5119 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5121 switch(vid.renderpath)
5123 case RENDERPATH_D3D9:
5125 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5126 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5129 case RENDERPATH_D3D10:
5130 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5132 case RENDERPATH_D3D11:
5133 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5135 case RENDERPATH_GL13:
5136 case RENDERPATH_GL11:
5137 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5139 case RENDERPATH_SOFT:
5140 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5141 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5143 case RENDERPATH_GL20:
5144 case RENDERPATH_GLES2:
5145 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5146 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5152 void R_ResetViewRendering2D(void)
5154 r_viewport_t viewport;
5157 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5158 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);
5159 R_SetViewport(&viewport);
5160 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5161 GL_Color(1, 1, 1, 1);
5162 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5163 GL_BlendFunc(GL_ONE, GL_ZERO);
5164 GL_ScissorTest(false);
5165 GL_DepthMask(false);
5166 GL_DepthRange(0, 1);
5167 GL_DepthTest(false);
5168 GL_DepthFunc(GL_LEQUAL);
5169 R_EntityMatrix(&identitymatrix);
5170 R_Mesh_ResetTextureState();
5171 GL_PolygonOffset(0, 0);
5172 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5173 switch(vid.renderpath)
5175 case RENDERPATH_GL11:
5176 case RENDERPATH_GL13:
5177 case RENDERPATH_GL20:
5178 case RENDERPATH_GLES2:
5179 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5181 case RENDERPATH_D3D9:
5182 case RENDERPATH_D3D10:
5183 case RENDERPATH_D3D11:
5184 case RENDERPATH_SOFT:
5187 GL_CullFace(GL_NONE);
5190 void R_ResetViewRendering3D(void)
5195 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5196 GL_Color(1, 1, 1, 1);
5197 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5198 GL_BlendFunc(GL_ONE, GL_ZERO);
5199 GL_ScissorTest(true);
5201 GL_DepthRange(0, 1);
5203 GL_DepthFunc(GL_LEQUAL);
5204 R_EntityMatrix(&identitymatrix);
5205 R_Mesh_ResetTextureState();
5206 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5207 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5208 switch(vid.renderpath)
5210 case RENDERPATH_GL11:
5211 case RENDERPATH_GL13:
5212 case RENDERPATH_GL20:
5213 case RENDERPATH_GLES2:
5214 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5216 case RENDERPATH_D3D9:
5217 case RENDERPATH_D3D10:
5218 case RENDERPATH_D3D11:
5219 case RENDERPATH_SOFT:
5222 GL_CullFace(r_refdef.view.cullface_back);
5227 R_RenderView_UpdateViewVectors
5230 static void R_RenderView_UpdateViewVectors(void)
5232 // break apart the view matrix into vectors for various purposes
5233 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5234 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5235 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5236 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5237 // make an inverted copy of the view matrix for tracking sprites
5238 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5241 void R_RenderScene(void);
5242 void R_RenderWaterPlanes(void);
5244 static void R_Water_StartFrame(void)
5247 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5248 r_waterstate_waterplane_t *p;
5250 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5253 switch(vid.renderpath)
5255 case RENDERPATH_GL20:
5256 case RENDERPATH_D3D9:
5257 case RENDERPATH_D3D10:
5258 case RENDERPATH_D3D11:
5259 case RENDERPATH_SOFT:
5260 case RENDERPATH_GLES2:
5262 case RENDERPATH_GL13:
5263 case RENDERPATH_GL11:
5267 // set waterwidth and waterheight to the water resolution that will be
5268 // used (often less than the screen resolution for faster rendering)
5269 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5270 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5272 // calculate desired texture sizes
5273 // can't use water if the card does not support the texture size
5274 if (!r_water.integer || r_showsurfaces.integer)
5275 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5276 else if (vid.support.arb_texture_non_power_of_two)
5278 texturewidth = waterwidth;
5279 textureheight = waterheight;
5280 camerawidth = waterwidth;
5281 cameraheight = waterheight;
5285 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5286 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5287 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5288 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5291 // allocate textures as needed
5292 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5294 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5295 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5297 if (p->texture_refraction)
5298 R_FreeTexture(p->texture_refraction);
5299 p->texture_refraction = NULL;
5300 if (p->texture_reflection)
5301 R_FreeTexture(p->texture_reflection);
5302 p->texture_reflection = NULL;
5303 if (p->texture_camera)
5304 R_FreeTexture(p->texture_camera);
5305 p->texture_camera = NULL;
5307 memset(&r_waterstate, 0, sizeof(r_waterstate));
5308 r_waterstate.texturewidth = texturewidth;
5309 r_waterstate.textureheight = textureheight;
5310 r_waterstate.camerawidth = camerawidth;
5311 r_waterstate.cameraheight = cameraheight;
5314 if (r_waterstate.texturewidth)
5316 r_waterstate.enabled = true;
5318 // when doing a reduced render (HDR) we want to use a smaller area
5319 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5320 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5322 // set up variables that will be used in shader setup
5323 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5324 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5325 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5326 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5329 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5330 r_waterstate.numwaterplanes = 0;
5333 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5335 int triangleindex, planeindex;
5341 r_waterstate_waterplane_t *p;
5342 texture_t *t = R_GetCurrentTexture(surface->texture);
5344 // just use the first triangle with a valid normal for any decisions
5345 VectorClear(normal);
5346 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5348 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5349 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5350 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5351 TriangleNormal(vert[0], vert[1], vert[2], normal);
5352 if (VectorLength2(normal) >= 0.001)
5356 VectorCopy(normal, plane.normal);
5357 VectorNormalize(plane.normal);
5358 plane.dist = DotProduct(vert[0], plane.normal);
5359 PlaneClassify(&plane);
5360 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5362 // skip backfaces (except if nocullface is set)
5363 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5365 VectorNegate(plane.normal, plane.normal);
5367 PlaneClassify(&plane);
5371 // find a matching plane if there is one
5372 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5373 if(p->camera_entity == t->camera_entity)
5374 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5376 if (planeindex >= r_waterstate.maxwaterplanes)
5377 return; // nothing we can do, out of planes
5379 // if this triangle does not fit any known plane rendered this frame, add one
5380 if (planeindex >= r_waterstate.numwaterplanes)
5382 // store the new plane
5383 r_waterstate.numwaterplanes++;
5385 // clear materialflags and pvs
5386 p->materialflags = 0;
5387 p->pvsvalid = false;
5388 p->camera_entity = t->camera_entity;
5389 VectorCopy(surface->mins, p->mins);
5390 VectorCopy(surface->maxs, p->maxs);
5395 p->mins[0] = min(p->mins[0], surface->mins[0]);
5396 p->mins[1] = min(p->mins[1], surface->mins[1]);
5397 p->mins[2] = min(p->mins[2], surface->mins[2]);
5398 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5399 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5400 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5402 // merge this surface's materialflags into the waterplane
5403 p->materialflags |= t->currentmaterialflags;
5404 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5406 // merge this surface's PVS into the waterplane
5407 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5408 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5409 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5411 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5417 static void R_Water_ProcessPlanes(void)
5420 r_refdef_view_t originalview;
5421 r_refdef_view_t myview;
5423 r_waterstate_waterplane_t *p;
5426 originalview = r_refdef.view;
5428 // make sure enough textures are allocated
5429 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5431 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5433 if (!p->texture_refraction)
5434 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);
5435 if (!p->texture_refraction)
5438 else if (p->materialflags & MATERIALFLAG_CAMERA)
5440 if (!p->texture_camera)
5441 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);
5442 if (!p->texture_camera)
5446 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5448 if (!p->texture_reflection)
5449 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);
5450 if (!p->texture_reflection)
5456 r_refdef.view = originalview;
5457 r_refdef.view.showdebug = false;
5458 r_refdef.view.width = r_waterstate.waterwidth;
5459 r_refdef.view.height = r_waterstate.waterheight;
5460 r_refdef.view.useclipplane = true;
5461 myview = r_refdef.view;
5462 r_waterstate.renderingscene = true;
5463 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5465 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5467 r_refdef.view = myview;
5468 if(r_water_scissormode.integer)
5471 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5472 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5475 // render reflected scene and copy into texture
5476 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5477 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5478 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5479 r_refdef.view.clipplane = p->plane;
5481 // reverse the cullface settings for this render
5482 r_refdef.view.cullface_front = GL_FRONT;
5483 r_refdef.view.cullface_back = GL_BACK;
5484 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5486 r_refdef.view.usecustompvs = true;
5488 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5490 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5493 R_ResetViewRendering3D();
5494 R_ClearScreen(r_refdef.fogenabled);
5495 if(r_water_scissormode.integer & 2)
5496 R_View_UpdateWithScissor(myscissor);
5499 if(r_water_scissormode.integer & 1)
5500 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5503 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);
5506 // render the normal view scene and copy into texture
5507 // (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)
5508 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5510 r_refdef.view = myview;
5511 if(r_water_scissormode.integer)
5514 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5515 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5518 r_waterstate.renderingrefraction = true;
5520 r_refdef.view.clipplane = p->plane;
5521 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5522 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5524 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5526 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5527 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5528 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5529 R_RenderView_UpdateViewVectors();
5530 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5532 r_refdef.view.usecustompvs = true;
5533 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);
5537 PlaneClassify(&r_refdef.view.clipplane);
5539 R_ResetViewRendering3D();
5540 R_ClearScreen(r_refdef.fogenabled);
5541 if(r_water_scissormode.integer & 2)
5542 R_View_UpdateWithScissor(myscissor);
5545 if(r_water_scissormode.integer & 1)
5546 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5549 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);
5550 r_waterstate.renderingrefraction = false;
5552 else if (p->materialflags & MATERIALFLAG_CAMERA)
5554 r_refdef.view = myview;
5556 r_refdef.view.clipplane = p->plane;
5557 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5558 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5560 r_refdef.view.width = r_waterstate.camerawidth;
5561 r_refdef.view.height = r_waterstate.cameraheight;
5562 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5563 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5565 if(p->camera_entity)
5567 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5568 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5571 // note: all of the view is used for displaying... so
5572 // there is no use in scissoring
5574 // reverse the cullface settings for this render
5575 r_refdef.view.cullface_front = GL_FRONT;
5576 r_refdef.view.cullface_back = GL_BACK;
5577 // also reverse the view matrix
5578 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
5579 R_RenderView_UpdateViewVectors();
5580 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5582 r_refdef.view.usecustompvs = true;
5583 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);
5586 // camera needs no clipplane
5587 r_refdef.view.useclipplane = false;
5589 PlaneClassify(&r_refdef.view.clipplane);
5591 R_ResetViewRendering3D();
5592 R_ClearScreen(r_refdef.fogenabled);
5596 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);
5597 r_waterstate.renderingrefraction = false;
5601 r_waterstate.renderingscene = false;
5602 r_refdef.view = originalview;
5603 R_ResetViewRendering3D();
5604 R_ClearScreen(r_refdef.fogenabled);
5608 r_refdef.view = originalview;
5609 r_waterstate.renderingscene = false;
5610 Cvar_SetValueQuick(&r_water, 0);
5611 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5615 void R_Bloom_StartFrame(void)
5617 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5619 switch(vid.renderpath)
5621 case RENDERPATH_GL20:
5622 case RENDERPATH_D3D9:
5623 case RENDERPATH_D3D10:
5624 case RENDERPATH_D3D11:
5625 case RENDERPATH_SOFT:
5626 case RENDERPATH_GLES2:
5628 case RENDERPATH_GL13:
5629 case RENDERPATH_GL11:
5633 // set bloomwidth and bloomheight to the bloom resolution that will be
5634 // used (often less than the screen resolution for faster rendering)
5635 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5636 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5637 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5638 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5639 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5641 // calculate desired texture sizes
5642 if (vid.support.arb_texture_non_power_of_two)
5644 screentexturewidth = r_refdef.view.width;
5645 screentextureheight = r_refdef.view.height;
5646 bloomtexturewidth = r_bloomstate.bloomwidth;
5647 bloomtextureheight = r_bloomstate.bloomheight;
5651 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5652 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5653 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5654 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5657 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))
5659 Cvar_SetValueQuick(&r_hdr, 0);
5660 Cvar_SetValueQuick(&r_bloom, 0);
5661 Cvar_SetValueQuick(&r_motionblur, 0);
5662 Cvar_SetValueQuick(&r_damageblur, 0);
5665 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)))
5666 screentexturewidth = screentextureheight = 0;
5667 if (!r_hdr.integer && !r_bloom.integer)
5668 bloomtexturewidth = bloomtextureheight = 0;
5670 // allocate textures as needed
5671 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5673 if (r_bloomstate.texture_screen)
5674 R_FreeTexture(r_bloomstate.texture_screen);
5675 r_bloomstate.texture_screen = NULL;
5676 r_bloomstate.screentexturewidth = screentexturewidth;
5677 r_bloomstate.screentextureheight = screentextureheight;
5678 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5679 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);
5681 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5683 if (r_bloomstate.texture_bloom)
5684 R_FreeTexture(r_bloomstate.texture_bloom);
5685 r_bloomstate.texture_bloom = NULL;
5686 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5687 r_bloomstate.bloomtextureheight = bloomtextureheight;
5688 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5689 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);
5692 // when doing a reduced render (HDR) we want to use a smaller area
5693 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5694 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5695 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5696 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5697 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5699 // set up a texcoord array for the full resolution screen image
5700 // (we have to keep this around to copy back during final render)
5701 r_bloomstate.screentexcoord2f[0] = 0;
5702 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5703 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5704 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5705 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5706 r_bloomstate.screentexcoord2f[5] = 0;
5707 r_bloomstate.screentexcoord2f[6] = 0;
5708 r_bloomstate.screentexcoord2f[7] = 0;
5710 // set up a texcoord array for the reduced resolution bloom image
5711 // (which will be additive blended over the screen image)
5712 r_bloomstate.bloomtexcoord2f[0] = 0;
5713 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5714 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5715 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5716 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5717 r_bloomstate.bloomtexcoord2f[5] = 0;
5718 r_bloomstate.bloomtexcoord2f[6] = 0;
5719 r_bloomstate.bloomtexcoord2f[7] = 0;
5721 switch(vid.renderpath)
5723 case RENDERPATH_GL11:
5724 case RENDERPATH_GL13:
5725 case RENDERPATH_GL20:
5726 case RENDERPATH_SOFT:
5727 case RENDERPATH_GLES2:
5729 case RENDERPATH_D3D9:
5730 case RENDERPATH_D3D10:
5731 case RENDERPATH_D3D11:
5734 for (i = 0;i < 4;i++)
5736 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5737 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5738 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5739 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5745 if (r_hdr.integer || r_bloom.integer)
5747 r_bloomstate.enabled = true;
5748 r_bloomstate.hdr = r_hdr.integer != 0;
5751 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);
5754 void R_Bloom_CopyBloomTexture(float colorscale)
5756 r_refdef.stats.bloom++;
5758 // scale down screen texture to the bloom texture size
5760 R_SetViewport(&r_bloomstate.viewport);
5761 GL_BlendFunc(GL_ONE, GL_ZERO);
5762 GL_Color(colorscale, colorscale, colorscale, 1);
5763 // 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...
5764 switch(vid.renderpath)
5766 case RENDERPATH_GL11:
5767 case RENDERPATH_GL13:
5768 case RENDERPATH_GL20:
5769 case RENDERPATH_SOFT:
5770 case RENDERPATH_GLES2:
5771 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5773 case RENDERPATH_D3D9:
5774 case RENDERPATH_D3D10:
5775 case RENDERPATH_D3D11:
5776 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5779 // TODO: do boxfilter scale-down in shader?
5780 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5781 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5782 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5784 // we now have a bloom image in the framebuffer
5785 // copy it into the bloom image texture for later processing
5786 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);
5787 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5790 void R_Bloom_CopyHDRTexture(void)
5792 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);
5793 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5796 void R_Bloom_MakeTexture(void)
5799 float xoffset, yoffset, r, brighten;
5801 r_refdef.stats.bloom++;
5803 R_ResetViewRendering2D();
5805 // we have a bloom image in the framebuffer
5807 R_SetViewport(&r_bloomstate.viewport);
5809 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5812 r = bound(0, r_bloom_colorexponent.value / x, 1);
5813 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5815 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5816 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5817 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5818 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5820 // copy the vertically blurred bloom view to a texture
5821 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);
5822 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5825 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5826 brighten = r_bloom_brighten.value;
5828 brighten *= r_hdr_range.value;
5829 brighten = sqrt(brighten);
5831 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5832 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5834 for (dir = 0;dir < 2;dir++)
5836 // blend on at multiple vertical offsets to achieve a vertical blur
5837 // TODO: do offset blends using GLSL
5838 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5839 GL_BlendFunc(GL_ONE, GL_ZERO);
5840 for (x = -range;x <= range;x++)
5842 if (!dir){xoffset = 0;yoffset = x;}
5843 else {xoffset = x;yoffset = 0;}
5844 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5845 yoffset /= (float)r_bloomstate.bloomtextureheight;
5846 // compute a texcoord array with the specified x and y offset
5847 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5848 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5849 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5850 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5851 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5852 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5853 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5854 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5855 // this r value looks like a 'dot' particle, fading sharply to
5856 // black at the edges
5857 // (probably not realistic but looks good enough)
5858 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5859 //r = brighten/(range*2+1);
5860 r = brighten / (range * 2 + 1);
5862 r *= (1 - x*x/(float)(range*range));
5863 GL_Color(r, r, r, 1);
5864 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5865 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5866 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5867 GL_BlendFunc(GL_ONE, GL_ONE);
5870 // copy the vertically blurred bloom view to a texture
5871 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);
5872 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5876 void R_HDR_RenderBloomTexture(void)
5878 int oldwidth, oldheight;
5879 float oldcolorscale;
5880 qboolean oldwaterstate;
5882 oldwaterstate = r_waterstate.enabled;
5883 oldcolorscale = r_refdef.view.colorscale;
5884 oldwidth = r_refdef.view.width;
5885 oldheight = r_refdef.view.height;
5886 r_refdef.view.width = r_bloomstate.bloomwidth;
5887 r_refdef.view.height = r_bloomstate.bloomheight;
5889 if(r_hdr.integer < 2)
5890 r_waterstate.enabled = false;
5892 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5893 // TODO: add exposure compensation features
5894 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5896 r_refdef.view.showdebug = false;
5897 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5899 R_ResetViewRendering3D();
5901 R_ClearScreen(r_refdef.fogenabled);
5902 if (r_timereport_active)
5903 R_TimeReport("HDRclear");
5906 if (r_timereport_active)
5907 R_TimeReport("visibility");
5909 // only do secondary renders with HDR if r_hdr is 2 or higher
5910 r_waterstate.numwaterplanes = 0;
5911 if (r_waterstate.enabled)
5912 R_RenderWaterPlanes();
5914 r_refdef.view.showdebug = true;
5916 r_waterstate.numwaterplanes = 0;
5918 R_ResetViewRendering2D();
5920 R_Bloom_CopyHDRTexture();
5921 R_Bloom_MakeTexture();
5923 // restore the view settings
5924 r_waterstate.enabled = oldwaterstate;
5925 r_refdef.view.width = oldwidth;
5926 r_refdef.view.height = oldheight;
5927 r_refdef.view.colorscale = oldcolorscale;
5929 R_ResetViewRendering3D();
5931 R_ClearScreen(r_refdef.fogenabled);
5932 if (r_timereport_active)
5933 R_TimeReport("viewclear");
5936 static void R_BlendView(void)
5938 unsigned int permutation;
5939 float uservecs[4][4];
5941 switch (vid.renderpath)
5943 case RENDERPATH_GL20:
5944 case RENDERPATH_D3D9:
5945 case RENDERPATH_D3D10:
5946 case RENDERPATH_D3D11:
5947 case RENDERPATH_SOFT:
5948 case RENDERPATH_GLES2:
5950 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5951 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5952 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5953 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5954 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5956 if (r_bloomstate.texture_screen)
5958 // make sure the buffer is available
5959 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5961 R_ResetViewRendering2D();
5963 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5965 // declare variables
5967 static float avgspeed;
5969 speed = VectorLength(cl.movement_velocity);
5971 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5972 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5974 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5975 speed = bound(0, speed, 1);
5976 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5978 // calculate values into a standard alpha
5979 cl.motionbluralpha = 1 - exp(-
5981 (r_motionblur.value * speed / 80)
5983 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5986 max(0.0001, cl.time - cl.oldtime) // fps independent
5989 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5990 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5992 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5994 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5995 GL_Color(1, 1, 1, cl.motionbluralpha);
5996 switch(vid.renderpath)
5998 case RENDERPATH_GL11:
5999 case RENDERPATH_GL13:
6000 case RENDERPATH_GL20:
6001 case RENDERPATH_SOFT:
6002 case RENDERPATH_GLES2:
6003 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6005 case RENDERPATH_D3D9:
6006 case RENDERPATH_D3D10:
6007 case RENDERPATH_D3D11:
6008 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6011 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6012 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6013 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6017 // copy view into the screen texture
6018 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);
6019 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6021 else if (!r_bloomstate.texture_bloom)
6023 // we may still have to do view tint...
6024 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6026 // apply a color tint to the whole view
6027 R_ResetViewRendering2D();
6028 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6029 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6030 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6031 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6032 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6034 break; // no screen processing, no bloom, skip it
6037 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6039 // render simple bloom effect
6040 // copy the screen and shrink it and darken it for the bloom process
6041 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6042 // make the bloom texture
6043 R_Bloom_MakeTexture();
6046 #if _MSC_VER >= 1400
6047 #define sscanf sscanf_s
6049 memset(uservecs, 0, sizeof(uservecs));
6050 if (r_glsl_postprocess_uservec1_enable.integer)
6051 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6052 if (r_glsl_postprocess_uservec2_enable.integer)
6053 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6054 if (r_glsl_postprocess_uservec3_enable.integer)
6055 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6056 if (r_glsl_postprocess_uservec4_enable.integer)
6057 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6059 R_ResetViewRendering2D();
6060 GL_Color(1, 1, 1, 1);
6061 GL_BlendFunc(GL_ONE, GL_ZERO);
6063 switch(vid.renderpath)
6065 case RENDERPATH_GL20:
6066 case RENDERPATH_GLES2:
6067 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6068 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6069 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6070 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6071 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6072 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]);
6073 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6074 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]);
6075 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]);
6076 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]);
6077 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]);
6078 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6079 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6080 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);
6082 case RENDERPATH_D3D9:
6084 // 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...
6085 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6086 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6087 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6088 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6089 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6090 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6091 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6092 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6093 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6094 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6095 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6096 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6097 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6098 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6101 case RENDERPATH_D3D10:
6102 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6104 case RENDERPATH_D3D11:
6105 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6107 case RENDERPATH_SOFT:
6108 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6109 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6110 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6111 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6112 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6113 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6114 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6115 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6116 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6117 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6118 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6119 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6120 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6121 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6126 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6127 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6129 case RENDERPATH_GL13:
6130 case RENDERPATH_GL11:
6131 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6133 // apply a color tint to the whole view
6134 R_ResetViewRendering2D();
6135 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6136 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6137 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6139 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6145 matrix4x4_t r_waterscrollmatrix;
6147 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6149 if (r_refdef.fog_density)
6151 r_refdef.fogcolor[0] = r_refdef.fog_red;
6152 r_refdef.fogcolor[1] = r_refdef.fog_green;
6153 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6155 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6156 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6157 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6158 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6162 VectorCopy(r_refdef.fogcolor, fogvec);
6163 // color.rgb *= ContrastBoost * SceneBrightness;
6164 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6165 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6166 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6167 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6172 void R_UpdateVariables(void)
6176 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6178 r_refdef.farclip = r_farclip_base.value;
6179 if (r_refdef.scene.worldmodel)
6180 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6181 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6183 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6184 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6185 r_refdef.polygonfactor = 0;
6186 r_refdef.polygonoffset = 0;
6187 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6188 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6190 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6191 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6192 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6193 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6194 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6195 if (FAKELIGHT_ENABLED)
6197 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6199 if (r_showsurfaces.integer)
6201 r_refdef.scene.rtworld = false;
6202 r_refdef.scene.rtworldshadows = false;
6203 r_refdef.scene.rtdlight = false;
6204 r_refdef.scene.rtdlightshadows = false;
6205 r_refdef.lightmapintensity = 0;
6208 if (gamemode == GAME_NEHAHRA)
6210 if (gl_fogenable.integer)
6212 r_refdef.oldgl_fogenable = true;
6213 r_refdef.fog_density = gl_fogdensity.value;
6214 r_refdef.fog_red = gl_fogred.value;
6215 r_refdef.fog_green = gl_foggreen.value;
6216 r_refdef.fog_blue = gl_fogblue.value;
6217 r_refdef.fog_alpha = 1;
6218 r_refdef.fog_start = 0;
6219 r_refdef.fog_end = gl_skyclip.value;
6220 r_refdef.fog_height = 1<<30;
6221 r_refdef.fog_fadedepth = 128;
6223 else if (r_refdef.oldgl_fogenable)
6225 r_refdef.oldgl_fogenable = false;
6226 r_refdef.fog_density = 0;
6227 r_refdef.fog_red = 0;
6228 r_refdef.fog_green = 0;
6229 r_refdef.fog_blue = 0;
6230 r_refdef.fog_alpha = 0;
6231 r_refdef.fog_start = 0;
6232 r_refdef.fog_end = 0;
6233 r_refdef.fog_height = 1<<30;
6234 r_refdef.fog_fadedepth = 128;
6238 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6239 r_refdef.fog_start = max(0, r_refdef.fog_start);
6240 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6242 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6244 if (r_refdef.fog_density && r_drawfog.integer)
6246 r_refdef.fogenabled = true;
6247 // this is the point where the fog reaches 0.9986 alpha, which we
6248 // consider a good enough cutoff point for the texture
6249 // (0.9986 * 256 == 255.6)
6250 if (r_fog_exp2.integer)
6251 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6253 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6254 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6255 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6256 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6257 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6258 R_BuildFogHeightTexture();
6259 // fog color was already set
6260 // update the fog texture
6261 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)
6262 R_BuildFogTexture();
6263 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6264 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6267 r_refdef.fogenabled = false;
6269 switch(vid.renderpath)
6271 case RENDERPATH_GL20:
6272 case RENDERPATH_D3D9:
6273 case RENDERPATH_D3D10:
6274 case RENDERPATH_D3D11:
6275 case RENDERPATH_SOFT:
6276 case RENDERPATH_GLES2:
6277 if(v_glslgamma.integer && !vid_gammatables_trivial)
6279 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6281 // build GLSL gamma texture
6282 #define RAMPWIDTH 256
6283 unsigned short ramp[RAMPWIDTH * 3];
6284 unsigned char rampbgr[RAMPWIDTH][4];
6287 r_texture_gammaramps_serial = vid_gammatables_serial;
6289 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6290 for(i = 0; i < RAMPWIDTH; ++i)
6292 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6293 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6294 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6297 if (r_texture_gammaramps)
6299 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6303 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6309 // remove GLSL gamma texture
6312 case RENDERPATH_GL13:
6313 case RENDERPATH_GL11:
6318 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6319 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6325 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6326 if( scenetype != r_currentscenetype ) {
6327 // store the old scenetype
6328 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6329 r_currentscenetype = scenetype;
6330 // move in the new scene
6331 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6340 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6342 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6343 if( scenetype == r_currentscenetype ) {
6344 return &r_refdef.scene;
6346 return &r_scenes_store[ scenetype ];
6355 int dpsoftrast_test;
6356 void R_RenderView(void)
6358 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6360 dpsoftrast_test = r_test.integer;
6362 if (r_timereport_active)
6363 R_TimeReport("start");
6364 r_textureframe++; // used only by R_GetCurrentTexture
6365 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6367 if(R_CompileShader_CheckStaticParms())
6370 if (!r_drawentities.integer)
6371 r_refdef.scene.numentities = 0;
6373 R_AnimCache_ClearCache();
6374 R_FrameData_NewFrame();
6376 /* adjust for stereo display */
6377 if(R_Stereo_Active())
6379 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);
6380 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6383 if (r_refdef.view.isoverlay)
6385 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6386 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6387 R_TimeReport("depthclear");
6389 r_refdef.view.showdebug = false;
6391 r_waterstate.enabled = false;
6392 r_waterstate.numwaterplanes = 0;
6396 r_refdef.view.matrix = originalmatrix;
6402 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6404 r_refdef.view.matrix = originalmatrix;
6405 return; //Host_Error ("R_RenderView: NULL worldmodel");
6408 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6410 R_RenderView_UpdateViewVectors();
6412 R_Shadow_UpdateWorldLightSelection();
6414 R_Bloom_StartFrame();
6415 R_Water_StartFrame();
6418 if (r_timereport_active)
6419 R_TimeReport("viewsetup");
6421 R_ResetViewRendering3D();
6423 if (r_refdef.view.clear || r_refdef.fogenabled)
6425 R_ClearScreen(r_refdef.fogenabled);
6426 if (r_timereport_active)
6427 R_TimeReport("viewclear");
6429 r_refdef.view.clear = true;
6431 // this produces a bloom texture to be used in R_BlendView() later
6432 if (r_hdr.integer && r_bloomstate.bloomwidth)
6434 R_HDR_RenderBloomTexture();
6435 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6436 r_textureframe++; // used only by R_GetCurrentTexture
6439 r_refdef.view.showdebug = true;
6442 if (r_timereport_active)
6443 R_TimeReport("visibility");
6445 r_waterstate.numwaterplanes = 0;
6446 if (r_waterstate.enabled)
6447 R_RenderWaterPlanes();
6450 r_waterstate.numwaterplanes = 0;
6453 if (r_timereport_active)
6454 R_TimeReport("blendview");
6456 GL_Scissor(0, 0, vid.width, vid.height);
6457 GL_ScissorTest(false);
6459 r_refdef.view.matrix = originalmatrix;
6464 void R_RenderWaterPlanes(void)
6466 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6468 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6469 if (r_timereport_active)
6470 R_TimeReport("waterworld");
6473 // don't let sound skip if going slow
6474 if (r_refdef.scene.extraupdate)
6477 R_DrawModelsAddWaterPlanes();
6478 if (r_timereport_active)
6479 R_TimeReport("watermodels");
6481 if (r_waterstate.numwaterplanes)
6483 R_Water_ProcessPlanes();
6484 if (r_timereport_active)
6485 R_TimeReport("waterscenes");
6489 extern void R_DrawLightningBeams (void);
6490 extern void VM_CL_AddPolygonsToMeshQueue (void);
6491 extern void R_DrawPortals (void);
6492 extern cvar_t cl_locs_show;
6493 static void R_DrawLocs(void);
6494 static void R_DrawEntityBBoxes(void);
6495 static void R_DrawModelDecals(void);
6496 extern void R_DrawModelShadows(void);
6497 extern void R_DrawModelShadowMaps(void);
6498 extern cvar_t cl_decals_newsystem;
6499 extern qboolean r_shadow_usingdeferredprepass;
6500 void R_RenderScene(void)
6502 qboolean shadowmapping = false;
6504 if (r_timereport_active)
6505 R_TimeReport("beginscene");
6507 r_refdef.stats.renders++;
6511 // don't let sound skip if going slow
6512 if (r_refdef.scene.extraupdate)
6515 R_MeshQueue_BeginScene();
6519 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);
6521 if (r_timereport_active)
6522 R_TimeReport("skystartframe");
6524 if (cl.csqc_vidvars.drawworld)
6526 // don't let sound skip if going slow
6527 if (r_refdef.scene.extraupdate)
6530 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6532 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6533 if (r_timereport_active)
6534 R_TimeReport("worldsky");
6537 if (R_DrawBrushModelsSky() && r_timereport_active)
6538 R_TimeReport("bmodelsky");
6540 if (skyrendermasked && skyrenderlater)
6542 // we have to force off the water clipping plane while rendering sky
6546 if (r_timereport_active)
6547 R_TimeReport("sky");
6551 R_AnimCache_CacheVisibleEntities();
6552 if (r_timereport_active)
6553 R_TimeReport("animation");
6555 R_Shadow_PrepareLights();
6556 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6557 R_Shadow_PrepareModelShadows();
6558 if (r_timereport_active)
6559 R_TimeReport("preparelights");
6561 if (R_Shadow_ShadowMappingEnabled())
6562 shadowmapping = true;
6564 if (r_shadow_usingdeferredprepass)
6565 R_Shadow_DrawPrepass();
6567 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6569 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6570 if (r_timereport_active)
6571 R_TimeReport("worlddepth");
6573 if (r_depthfirst.integer >= 2)
6575 R_DrawModelsDepth();
6576 if (r_timereport_active)
6577 R_TimeReport("modeldepth");
6580 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6582 R_DrawModelShadowMaps();
6583 R_ResetViewRendering3D();
6584 // don't let sound skip if going slow
6585 if (r_refdef.scene.extraupdate)
6589 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6591 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6592 if (r_timereport_active)
6593 R_TimeReport("world");
6596 // don't let sound skip if going slow
6597 if (r_refdef.scene.extraupdate)
6601 if (r_timereport_active)
6602 R_TimeReport("models");
6604 // don't let sound skip if going slow
6605 if (r_refdef.scene.extraupdate)
6608 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6610 R_DrawModelShadows();
6611 R_ResetViewRendering3D();
6612 // don't let sound skip if going slow
6613 if (r_refdef.scene.extraupdate)
6617 if (!r_shadow_usingdeferredprepass)
6619 R_Shadow_DrawLights();
6620 if (r_timereport_active)
6621 R_TimeReport("rtlights");
6624 // don't let sound skip if going slow
6625 if (r_refdef.scene.extraupdate)
6628 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6630 R_DrawModelShadows();
6631 R_ResetViewRendering3D();
6632 // don't let sound skip if going slow
6633 if (r_refdef.scene.extraupdate)
6637 if (cl.csqc_vidvars.drawworld)
6639 if (cl_decals_newsystem.integer)
6641 R_DrawModelDecals();
6642 if (r_timereport_active)
6643 R_TimeReport("modeldecals");
6648 if (r_timereport_active)
6649 R_TimeReport("decals");
6653 if (r_timereport_active)
6654 R_TimeReport("particles");
6657 if (r_timereport_active)
6658 R_TimeReport("explosions");
6660 R_DrawLightningBeams();
6661 if (r_timereport_active)
6662 R_TimeReport("lightning");
6665 VM_CL_AddPolygonsToMeshQueue();
6667 if (r_refdef.view.showdebug)
6669 if (cl_locs_show.integer)
6672 if (r_timereport_active)
6673 R_TimeReport("showlocs");
6676 if (r_drawportals.integer)
6679 if (r_timereport_active)
6680 R_TimeReport("portals");
6683 if (r_showbboxes.value > 0)
6685 R_DrawEntityBBoxes();
6686 if (r_timereport_active)
6687 R_TimeReport("bboxes");
6691 R_MeshQueue_RenderTransparent();
6692 if (r_timereport_active)
6693 R_TimeReport("drawtrans");
6695 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))
6697 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6698 if (r_timereport_active)
6699 R_TimeReport("worlddebug");
6700 R_DrawModelsDebug();
6701 if (r_timereport_active)
6702 R_TimeReport("modeldebug");
6705 if (cl.csqc_vidvars.drawworld)
6707 R_Shadow_DrawCoronas();
6708 if (r_timereport_active)
6709 R_TimeReport("coronas");
6714 GL_DepthTest(false);
6715 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6716 GL_Color(1, 1, 1, 1);
6717 qglBegin(GL_POLYGON);
6718 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6719 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6720 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6721 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6723 qglBegin(GL_POLYGON);
6724 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]);
6725 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]);
6726 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]);
6727 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]);
6729 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6733 // don't let sound skip if going slow
6734 if (r_refdef.scene.extraupdate)
6737 R_ResetViewRendering2D();
6740 static const unsigned short bboxelements[36] =
6750 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6753 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6755 RSurf_ActiveWorldEntity();
6757 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6758 GL_DepthMask(false);
6759 GL_DepthRange(0, 1);
6760 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6761 // R_Mesh_ResetTextureState();
6763 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6764 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6765 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6766 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6767 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6768 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6769 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6770 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6771 R_FillColors(color4f, 8, cr, cg, cb, ca);
6772 if (r_refdef.fogenabled)
6774 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6776 f1 = RSurf_FogVertex(v);
6778 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6779 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6780 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6783 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6784 R_Mesh_ResetTextureState();
6785 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6786 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6789 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6793 prvm_edict_t *edict;
6794 prvm_prog_t *prog_save = prog;
6796 // this function draws bounding boxes of server entities
6800 GL_CullFace(GL_NONE);
6801 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6805 for (i = 0;i < numsurfaces;i++)
6807 edict = PRVM_EDICT_NUM(surfacelist[i]);
6808 switch ((int)edict->fields.server->solid)
6810 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6811 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6812 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6813 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6814 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6815 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6817 color[3] *= r_showbboxes.value;
6818 color[3] = bound(0, color[3], 1);
6819 GL_DepthTest(!r_showdisabledepthtest.integer);
6820 GL_CullFace(r_refdef.view.cullface_front);
6821 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6827 static void R_DrawEntityBBoxes(void)
6830 prvm_edict_t *edict;
6832 prvm_prog_t *prog_save = prog;
6834 // this function draws bounding boxes of server entities
6840 for (i = 0;i < prog->num_edicts;i++)
6842 edict = PRVM_EDICT_NUM(i);
6843 if (edict->priv.server->free)
6845 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6846 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6848 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6850 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6851 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6857 static const int nomodelelement3i[24] =
6869 static const unsigned short nomodelelement3s[24] =
6881 static const float nomodelvertex3f[6*3] =
6891 static const float nomodelcolor4f[6*4] =
6893 0.0f, 0.0f, 0.5f, 1.0f,
6894 0.0f, 0.0f, 0.5f, 1.0f,
6895 0.0f, 0.5f, 0.0f, 1.0f,
6896 0.0f, 0.5f, 0.0f, 1.0f,
6897 0.5f, 0.0f, 0.0f, 1.0f,
6898 0.5f, 0.0f, 0.0f, 1.0f
6901 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6907 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);
6909 // this is only called once per entity so numsurfaces is always 1, and
6910 // surfacelist is always {0}, so this code does not handle batches
6912 if (rsurface.ent_flags & RENDER_ADDITIVE)
6914 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6915 GL_DepthMask(false);
6917 else if (rsurface.colormod[3] < 1)
6919 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6920 GL_DepthMask(false);
6924 GL_BlendFunc(GL_ONE, GL_ZERO);
6927 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6928 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6929 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6930 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6931 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6932 for (i = 0, c = color4f;i < 6;i++, c += 4)
6934 c[0] *= rsurface.colormod[0];
6935 c[1] *= rsurface.colormod[1];
6936 c[2] *= rsurface.colormod[2];
6937 c[3] *= rsurface.colormod[3];
6939 if (r_refdef.fogenabled)
6941 for (i = 0, c = color4f;i < 6;i++, c += 4)
6943 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6945 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6946 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6947 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6950 // R_Mesh_ResetTextureState();
6951 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6952 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6953 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6956 void R_DrawNoModel(entity_render_t *ent)
6959 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6960 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6961 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6963 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6966 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6968 vec3_t right1, right2, diff, normal;
6970 VectorSubtract (org2, org1, normal);
6972 // calculate 'right' vector for start
6973 VectorSubtract (r_refdef.view.origin, org1, diff);
6974 CrossProduct (normal, diff, right1);
6975 VectorNormalize (right1);
6977 // calculate 'right' vector for end
6978 VectorSubtract (r_refdef.view.origin, org2, diff);
6979 CrossProduct (normal, diff, right2);
6980 VectorNormalize (right2);
6982 vert[ 0] = org1[0] + width * right1[0];
6983 vert[ 1] = org1[1] + width * right1[1];
6984 vert[ 2] = org1[2] + width * right1[2];
6985 vert[ 3] = org1[0] - width * right1[0];
6986 vert[ 4] = org1[1] - width * right1[1];
6987 vert[ 5] = org1[2] - width * right1[2];
6988 vert[ 6] = org2[0] - width * right2[0];
6989 vert[ 7] = org2[1] - width * right2[1];
6990 vert[ 8] = org2[2] - width * right2[2];
6991 vert[ 9] = org2[0] + width * right2[0];
6992 vert[10] = org2[1] + width * right2[1];
6993 vert[11] = org2[2] + width * right2[2];
6996 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)
6998 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6999 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7000 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7001 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7002 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7003 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7004 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7005 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7006 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7007 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7008 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7009 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7012 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7017 VectorSet(v, x, y, z);
7018 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7019 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7021 if (i == mesh->numvertices)
7023 if (mesh->numvertices < mesh->maxvertices)
7025 VectorCopy(v, vertex3f);
7026 mesh->numvertices++;
7028 return mesh->numvertices;
7034 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7038 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7039 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7040 e = mesh->element3i + mesh->numtriangles * 3;
7041 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7043 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7044 if (mesh->numtriangles < mesh->maxtriangles)
7049 mesh->numtriangles++;
7051 element[1] = element[2];
7055 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7059 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7060 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7061 e = mesh->element3i + mesh->numtriangles * 3;
7062 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7064 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7065 if (mesh->numtriangles < mesh->maxtriangles)
7070 mesh->numtriangles++;
7072 element[1] = element[2];
7076 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7077 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7079 int planenum, planenum2;
7082 mplane_t *plane, *plane2;
7084 double temppoints[2][256*3];
7085 // figure out how large a bounding box we need to properly compute this brush
7087 for (w = 0;w < numplanes;w++)
7088 maxdist = max(maxdist, fabs(planes[w].dist));
7089 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7090 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7091 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7095 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7096 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7098 if (planenum2 == planenum)
7100 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);
7103 if (tempnumpoints < 3)
7105 // generate elements forming a triangle fan for this polygon
7106 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7110 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)
7112 texturelayer_t *layer;
7113 layer = t->currentlayers + t->currentnumlayers++;
7115 layer->depthmask = depthmask;
7116 layer->blendfunc1 = blendfunc1;
7117 layer->blendfunc2 = blendfunc2;
7118 layer->texture = texture;
7119 layer->texmatrix = *matrix;
7120 layer->color[0] = r;
7121 layer->color[1] = g;
7122 layer->color[2] = b;
7123 layer->color[3] = a;
7126 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7128 if(parms[0] == 0 && parms[1] == 0)
7130 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7131 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7136 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7139 index = parms[2] + r_refdef.scene.time * parms[3];
7140 index -= floor(index);
7141 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7144 case Q3WAVEFUNC_NONE:
7145 case Q3WAVEFUNC_NOISE:
7146 case Q3WAVEFUNC_COUNT:
7149 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7150 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7151 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7152 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7153 case Q3WAVEFUNC_TRIANGLE:
7155 f = index - floor(index);
7166 f = parms[0] + parms[1] * f;
7167 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7168 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7172 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7177 matrix4x4_t matrix, temp;
7178 switch(tcmod->tcmod)
7182 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7183 matrix = r_waterscrollmatrix;
7185 matrix = identitymatrix;
7187 case Q3TCMOD_ENTITYTRANSLATE:
7188 // this is used in Q3 to allow the gamecode to control texcoord
7189 // scrolling on the entity, which is not supported in darkplaces yet.
7190 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7192 case Q3TCMOD_ROTATE:
7193 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7194 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7195 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7198 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7200 case Q3TCMOD_SCROLL:
7201 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7203 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7204 w = (int) tcmod->parms[0];
7205 h = (int) tcmod->parms[1];
7206 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7208 idx = (int) floor(f * w * h);
7209 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7211 case Q3TCMOD_STRETCH:
7212 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7213 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7215 case Q3TCMOD_TRANSFORM:
7216 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7217 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7218 VectorSet(tcmat + 6, 0 , 0 , 1);
7219 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7220 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7222 case Q3TCMOD_TURBULENT:
7223 // this is handled in the RSurf_PrepareVertices function
7224 matrix = identitymatrix;
7228 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7231 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7233 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7234 char name[MAX_QPATH];
7235 skinframe_t *skinframe;
7236 unsigned char pixels[296*194];
7237 strlcpy(cache->name, skinname, sizeof(cache->name));
7238 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7239 if (developer_loading.integer)
7240 Con_Printf("loading %s\n", name);
7241 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7242 if (!skinframe || !skinframe->base)
7245 fs_offset_t filesize;
7247 f = FS_LoadFile(name, tempmempool, true, &filesize);
7250 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7251 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7255 cache->skinframe = skinframe;
7258 texture_t *R_GetCurrentTexture(texture_t *t)
7261 const entity_render_t *ent = rsurface.entity;
7262 dp_model_t *model = ent->model;
7263 q3shaderinfo_layer_tcmod_t *tcmod;
7265 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7266 return t->currentframe;
7267 t->update_lastrenderframe = r_textureframe;
7268 t->update_lastrenderentity = (void *)ent;
7270 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7271 t->camera_entity = ent->entitynumber;
7273 t->camera_entity = 0;
7275 // switch to an alternate material if this is a q1bsp animated material
7277 texture_t *texture = t;
7278 int s = rsurface.ent_skinnum;
7279 if ((unsigned int)s >= (unsigned int)model->numskins)
7281 if (model->skinscenes)
7283 if (model->skinscenes[s].framecount > 1)
7284 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7286 s = model->skinscenes[s].firstframe;
7289 t = t + s * model->num_surfaces;
7292 // use an alternate animation if the entity's frame is not 0,
7293 // and only if the texture has an alternate animation
7294 if (rsurface.ent_alttextures && t->anim_total[1])
7295 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7297 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7299 texture->currentframe = t;
7302 // update currentskinframe to be a qw skin or animation frame
7303 if (rsurface.ent_qwskin >= 0)
7305 i = rsurface.ent_qwskin;
7306 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7308 r_qwskincache_size = cl.maxclients;
7310 Mem_Free(r_qwskincache);
7311 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7313 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7314 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7315 t->currentskinframe = r_qwskincache[i].skinframe;
7316 if (t->currentskinframe == NULL)
7317 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7319 else if (t->numskinframes >= 2)
7320 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7321 if (t->backgroundnumskinframes >= 2)
7322 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7324 t->currentmaterialflags = t->basematerialflags;
7325 t->currentalpha = rsurface.colormod[3];
7326 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7327 t->currentalpha *= r_wateralpha.value;
7328 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7329 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7330 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7331 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7332 if (!(rsurface.ent_flags & RENDER_LIGHT))
7333 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7334 else if (FAKELIGHT_ENABLED)
7336 // no modellight if using fakelight for the map
7338 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7340 // pick a model lighting mode
7341 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7342 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7344 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7346 if (rsurface.ent_flags & RENDER_ADDITIVE)
7347 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7348 else if (t->currentalpha < 1)
7349 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7350 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7351 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7352 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7353 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7354 if (t->backgroundnumskinframes)
7355 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7356 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7358 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7359 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7362 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7363 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7364 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7366 // there is no tcmod
7367 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7369 t->currenttexmatrix = r_waterscrollmatrix;
7370 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7372 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7374 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7375 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7378 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7379 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7380 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7381 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7383 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7384 if (t->currentskinframe->qpixels)
7385 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7386 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7387 if (!t->basetexture)
7388 t->basetexture = r_texture_notexture;
7389 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7390 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7391 t->nmaptexture = t->currentskinframe->nmap;
7392 if (!t->nmaptexture)
7393 t->nmaptexture = r_texture_blanknormalmap;
7394 t->glosstexture = r_texture_black;
7395 t->glowtexture = t->currentskinframe->glow;
7396 t->fogtexture = t->currentskinframe->fog;
7397 t->reflectmasktexture = t->currentskinframe->reflect;
7398 if (t->backgroundnumskinframes)
7400 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7401 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7402 t->backgroundglosstexture = r_texture_black;
7403 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7404 if (!t->backgroundnmaptexture)
7405 t->backgroundnmaptexture = r_texture_blanknormalmap;
7409 t->backgroundbasetexture = r_texture_white;
7410 t->backgroundnmaptexture = r_texture_blanknormalmap;
7411 t->backgroundglosstexture = r_texture_black;
7412 t->backgroundglowtexture = NULL;
7414 t->specularpower = r_shadow_glossexponent.value;
7415 // TODO: store reference values for these in the texture?
7416 t->specularscale = 0;
7417 if (r_shadow_gloss.integer > 0)
7419 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7421 if (r_shadow_glossintensity.value > 0)
7423 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7424 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7425 t->specularscale = r_shadow_glossintensity.value;
7428 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7430 t->glosstexture = r_texture_white;
7431 t->backgroundglosstexture = r_texture_white;
7432 t->specularscale = r_shadow_gloss2intensity.value;
7433 t->specularpower = r_shadow_gloss2exponent.value;
7436 t->specularscale *= t->specularscalemod;
7437 t->specularpower *= t->specularpowermod;
7439 // lightmaps mode looks bad with dlights using actual texturing, so turn
7440 // off the colormap and glossmap, but leave the normalmap on as it still
7441 // accurately represents the shading involved
7442 if (gl_lightmaps.integer)
7444 t->basetexture = r_texture_grey128;
7445 t->pantstexture = r_texture_black;
7446 t->shirttexture = r_texture_black;
7447 t->nmaptexture = r_texture_blanknormalmap;
7448 t->glosstexture = r_texture_black;
7449 t->glowtexture = NULL;
7450 t->fogtexture = NULL;
7451 t->reflectmasktexture = NULL;
7452 t->backgroundbasetexture = NULL;
7453 t->backgroundnmaptexture = r_texture_blanknormalmap;
7454 t->backgroundglosstexture = r_texture_black;
7455 t->backgroundglowtexture = NULL;
7456 t->specularscale = 0;
7457 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7460 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7461 VectorClear(t->dlightcolor);
7462 t->currentnumlayers = 0;
7463 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7465 int blendfunc1, blendfunc2;
7467 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7469 blendfunc1 = GL_SRC_ALPHA;
7470 blendfunc2 = GL_ONE;
7472 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7474 blendfunc1 = GL_SRC_ALPHA;
7475 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7477 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7479 blendfunc1 = t->customblendfunc[0];
7480 blendfunc2 = t->customblendfunc[1];
7484 blendfunc1 = GL_ONE;
7485 blendfunc2 = GL_ZERO;
7487 // don't colormod evilblend textures
7488 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7489 VectorSet(t->lightmapcolor, 1, 1, 1);
7490 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7491 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7493 // fullbright is not affected by r_refdef.lightmapintensity
7494 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]);
7495 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7496 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]);
7497 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7498 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]);
7502 vec3_t ambientcolor;
7504 // set the color tint used for lights affecting this surface
7505 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7507 // q3bsp has no lightmap updates, so the lightstylevalue that
7508 // would normally be baked into the lightmap must be
7509 // applied to the color
7510 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7511 if (model->type == mod_brushq3)
7512 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7513 colorscale *= r_refdef.lightmapintensity;
7514 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7515 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7516 // basic lit geometry
7517 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]);
7518 // add pants/shirt if needed
7519 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7520 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]);
7521 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7522 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]);
7523 // now add ambient passes if needed
7524 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7526 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]);
7527 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7528 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]);
7529 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7530 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]);
7533 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7534 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]);
7535 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7537 // if this is opaque use alpha blend which will darken the earlier
7540 // if this is an alpha blended material, all the earlier passes
7541 // were darkened by fog already, so we only need to add the fog
7542 // color ontop through the fog mask texture
7544 // if this is an additive blended material, all the earlier passes
7545 // were darkened by fog already, and we should not add fog color
7546 // (because the background was not darkened, there is no fog color
7547 // that was lost behind it).
7548 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]);
7552 return t->currentframe;
7555 rsurfacestate_t rsurface;
7557 void RSurf_ActiveWorldEntity(void)
7559 dp_model_t *model = r_refdef.scene.worldmodel;
7560 //if (rsurface.entity == r_refdef.scene.worldentity)
7562 rsurface.entity = r_refdef.scene.worldentity;
7563 rsurface.skeleton = NULL;
7564 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7565 rsurface.ent_skinnum = 0;
7566 rsurface.ent_qwskin = -1;
7567 rsurface.ent_shadertime = 0;
7568 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7569 rsurface.matrix = identitymatrix;
7570 rsurface.inversematrix = identitymatrix;
7571 rsurface.matrixscale = 1;
7572 rsurface.inversematrixscale = 1;
7573 R_EntityMatrix(&identitymatrix);
7574 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7575 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7576 rsurface.fograngerecip = r_refdef.fograngerecip;
7577 rsurface.fogheightfade = r_refdef.fogheightfade;
7578 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7579 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7580 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7581 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7582 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7583 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7584 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7585 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7586 rsurface.colormod[3] = 1;
7587 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);
7588 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7589 rsurface.frameblend[0].lerp = 1;
7590 rsurface.ent_alttextures = false;
7591 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7592 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7593 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7594 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7595 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7596 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7597 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7598 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7599 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7600 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7601 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7602 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7603 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7604 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7605 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7606 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7607 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7608 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7609 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7610 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7611 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7612 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7613 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7614 rsurface.modelelement3i = model->surfmesh.data_element3i;
7615 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7616 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7617 rsurface.modelelement3s = model->surfmesh.data_element3s;
7618 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7619 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7620 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7621 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7622 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7623 rsurface.modelsurfaces = model->data_surfaces;
7624 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7625 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7626 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7627 rsurface.modelgeneratedvertex = false;
7628 rsurface.batchgeneratedvertex = false;
7629 rsurface.batchfirstvertex = 0;
7630 rsurface.batchnumvertices = 0;
7631 rsurface.batchfirsttriangle = 0;
7632 rsurface.batchnumtriangles = 0;
7633 rsurface.batchvertex3f = NULL;
7634 rsurface.batchvertex3f_vertexbuffer = NULL;
7635 rsurface.batchvertex3f_bufferoffset = 0;
7636 rsurface.batchsvector3f = NULL;
7637 rsurface.batchsvector3f_vertexbuffer = NULL;
7638 rsurface.batchsvector3f_bufferoffset = 0;
7639 rsurface.batchtvector3f = NULL;
7640 rsurface.batchtvector3f_vertexbuffer = NULL;
7641 rsurface.batchtvector3f_bufferoffset = 0;
7642 rsurface.batchnormal3f = NULL;
7643 rsurface.batchnormal3f_vertexbuffer = NULL;
7644 rsurface.batchnormal3f_bufferoffset = 0;
7645 rsurface.batchlightmapcolor4f = NULL;
7646 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7647 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7648 rsurface.batchtexcoordtexture2f = NULL;
7649 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7650 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7651 rsurface.batchtexcoordlightmap2f = NULL;
7652 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7653 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7654 rsurface.batchvertexmesh = NULL;
7655 rsurface.batchvertexmeshbuffer = NULL;
7656 rsurface.batchvertex3fbuffer = NULL;
7657 rsurface.batchelement3i = NULL;
7658 rsurface.batchelement3i_indexbuffer = NULL;
7659 rsurface.batchelement3i_bufferoffset = 0;
7660 rsurface.batchelement3s = NULL;
7661 rsurface.batchelement3s_indexbuffer = NULL;
7662 rsurface.batchelement3s_bufferoffset = 0;
7663 rsurface.passcolor4f = NULL;
7664 rsurface.passcolor4f_vertexbuffer = NULL;
7665 rsurface.passcolor4f_bufferoffset = 0;
7668 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7670 dp_model_t *model = ent->model;
7671 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7673 rsurface.entity = (entity_render_t *)ent;
7674 rsurface.skeleton = ent->skeleton;
7675 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7676 rsurface.ent_skinnum = ent->skinnum;
7677 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;
7678 rsurface.ent_shadertime = ent->shadertime;
7679 rsurface.ent_flags = ent->flags;
7680 rsurface.matrix = ent->matrix;
7681 rsurface.inversematrix = ent->inversematrix;
7682 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7683 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7684 R_EntityMatrix(&rsurface.matrix);
7685 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7686 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7687 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7688 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7689 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7690 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7691 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7692 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7693 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7694 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7695 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7696 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7697 rsurface.colormod[3] = ent->alpha;
7698 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7699 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7700 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7701 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7702 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7703 if (ent->model->brush.submodel && !prepass)
7705 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7706 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7708 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7710 if (ent->animcache_vertex3f)
7712 rsurface.modelvertex3f = ent->animcache_vertex3f;
7713 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7714 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7715 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7716 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7717 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7718 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7720 else if (wanttangents)
7722 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7723 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7724 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7725 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7726 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7727 rsurface.modelvertexmesh = NULL;
7728 rsurface.modelvertexmeshbuffer = NULL;
7729 rsurface.modelvertex3fbuffer = NULL;
7731 else if (wantnormals)
7733 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7734 rsurface.modelsvector3f = NULL;
7735 rsurface.modeltvector3f = NULL;
7736 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7737 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7738 rsurface.modelvertexmesh = NULL;
7739 rsurface.modelvertexmeshbuffer = NULL;
7740 rsurface.modelvertex3fbuffer = NULL;
7744 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7745 rsurface.modelsvector3f = NULL;
7746 rsurface.modeltvector3f = NULL;
7747 rsurface.modelnormal3f = NULL;
7748 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7749 rsurface.modelvertexmesh = NULL;
7750 rsurface.modelvertexmeshbuffer = NULL;
7751 rsurface.modelvertex3fbuffer = NULL;
7753 rsurface.modelvertex3f_vertexbuffer = 0;
7754 rsurface.modelvertex3f_bufferoffset = 0;
7755 rsurface.modelsvector3f_vertexbuffer = 0;
7756 rsurface.modelsvector3f_bufferoffset = 0;
7757 rsurface.modeltvector3f_vertexbuffer = 0;
7758 rsurface.modeltvector3f_bufferoffset = 0;
7759 rsurface.modelnormal3f_vertexbuffer = 0;
7760 rsurface.modelnormal3f_bufferoffset = 0;
7761 rsurface.modelgeneratedvertex = true;
7765 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7766 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7767 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7768 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7769 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7770 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7771 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7772 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7773 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7774 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7775 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7776 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7777 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7778 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7779 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7780 rsurface.modelgeneratedvertex = false;
7782 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7783 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7784 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7785 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7786 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7787 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7788 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7789 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7790 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7791 rsurface.modelelement3i = model->surfmesh.data_element3i;
7792 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7793 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7794 rsurface.modelelement3s = model->surfmesh.data_element3s;
7795 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7796 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7797 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7798 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7799 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7800 rsurface.modelsurfaces = model->data_surfaces;
7801 rsurface.batchgeneratedvertex = false;
7802 rsurface.batchfirstvertex = 0;
7803 rsurface.batchnumvertices = 0;
7804 rsurface.batchfirsttriangle = 0;
7805 rsurface.batchnumtriangles = 0;
7806 rsurface.batchvertex3f = NULL;
7807 rsurface.batchvertex3f_vertexbuffer = NULL;
7808 rsurface.batchvertex3f_bufferoffset = 0;
7809 rsurface.batchsvector3f = NULL;
7810 rsurface.batchsvector3f_vertexbuffer = NULL;
7811 rsurface.batchsvector3f_bufferoffset = 0;
7812 rsurface.batchtvector3f = NULL;
7813 rsurface.batchtvector3f_vertexbuffer = NULL;
7814 rsurface.batchtvector3f_bufferoffset = 0;
7815 rsurface.batchnormal3f = NULL;
7816 rsurface.batchnormal3f_vertexbuffer = NULL;
7817 rsurface.batchnormal3f_bufferoffset = 0;
7818 rsurface.batchlightmapcolor4f = NULL;
7819 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7820 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7821 rsurface.batchtexcoordtexture2f = NULL;
7822 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7823 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7824 rsurface.batchtexcoordlightmap2f = NULL;
7825 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7826 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7827 rsurface.batchvertexmesh = NULL;
7828 rsurface.batchvertexmeshbuffer = NULL;
7829 rsurface.batchvertex3fbuffer = NULL;
7830 rsurface.batchelement3i = NULL;
7831 rsurface.batchelement3i_indexbuffer = NULL;
7832 rsurface.batchelement3i_bufferoffset = 0;
7833 rsurface.batchelement3s = NULL;
7834 rsurface.batchelement3s_indexbuffer = NULL;
7835 rsurface.batchelement3s_bufferoffset = 0;
7836 rsurface.passcolor4f = NULL;
7837 rsurface.passcolor4f_vertexbuffer = NULL;
7838 rsurface.passcolor4f_bufferoffset = 0;
7841 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)
7843 rsurface.entity = r_refdef.scene.worldentity;
7844 rsurface.skeleton = NULL;
7845 rsurface.ent_skinnum = 0;
7846 rsurface.ent_qwskin = -1;
7847 rsurface.ent_shadertime = shadertime;
7848 rsurface.ent_flags = entflags;
7849 rsurface.modelnumvertices = numvertices;
7850 rsurface.modelnumtriangles = numtriangles;
7851 rsurface.matrix = *matrix;
7852 rsurface.inversematrix = *inversematrix;
7853 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7854 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7855 R_EntityMatrix(&rsurface.matrix);
7856 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7857 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7858 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7859 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7860 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7861 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7862 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7863 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7864 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7865 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7866 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7867 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7868 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);
7869 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7870 rsurface.frameblend[0].lerp = 1;
7871 rsurface.ent_alttextures = false;
7872 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7873 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7876 rsurface.modelvertex3f = (float *)vertex3f;
7877 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7878 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7879 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7881 else if (wantnormals)
7883 rsurface.modelvertex3f = (float *)vertex3f;
7884 rsurface.modelsvector3f = NULL;
7885 rsurface.modeltvector3f = NULL;
7886 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7890 rsurface.modelvertex3f = (float *)vertex3f;
7891 rsurface.modelsvector3f = NULL;
7892 rsurface.modeltvector3f = NULL;
7893 rsurface.modelnormal3f = NULL;
7895 rsurface.modelvertexmesh = NULL;
7896 rsurface.modelvertexmeshbuffer = NULL;
7897 rsurface.modelvertex3fbuffer = NULL;
7898 rsurface.modelvertex3f_vertexbuffer = 0;
7899 rsurface.modelvertex3f_bufferoffset = 0;
7900 rsurface.modelsvector3f_vertexbuffer = 0;
7901 rsurface.modelsvector3f_bufferoffset = 0;
7902 rsurface.modeltvector3f_vertexbuffer = 0;
7903 rsurface.modeltvector3f_bufferoffset = 0;
7904 rsurface.modelnormal3f_vertexbuffer = 0;
7905 rsurface.modelnormal3f_bufferoffset = 0;
7906 rsurface.modelgeneratedvertex = true;
7907 rsurface.modellightmapcolor4f = (float *)color4f;
7908 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7909 rsurface.modellightmapcolor4f_bufferoffset = 0;
7910 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7911 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7912 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7913 rsurface.modeltexcoordlightmap2f = NULL;
7914 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7915 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7916 rsurface.modelelement3i = (int *)element3i;
7917 rsurface.modelelement3i_indexbuffer = NULL;
7918 rsurface.modelelement3i_bufferoffset = 0;
7919 rsurface.modelelement3s = (unsigned short *)element3s;
7920 rsurface.modelelement3s_indexbuffer = NULL;
7921 rsurface.modelelement3s_bufferoffset = 0;
7922 rsurface.modellightmapoffsets = NULL;
7923 rsurface.modelsurfaces = NULL;
7924 rsurface.batchgeneratedvertex = false;
7925 rsurface.batchfirstvertex = 0;
7926 rsurface.batchnumvertices = 0;
7927 rsurface.batchfirsttriangle = 0;
7928 rsurface.batchnumtriangles = 0;
7929 rsurface.batchvertex3f = NULL;
7930 rsurface.batchvertex3f_vertexbuffer = NULL;
7931 rsurface.batchvertex3f_bufferoffset = 0;
7932 rsurface.batchsvector3f = NULL;
7933 rsurface.batchsvector3f_vertexbuffer = NULL;
7934 rsurface.batchsvector3f_bufferoffset = 0;
7935 rsurface.batchtvector3f = NULL;
7936 rsurface.batchtvector3f_vertexbuffer = NULL;
7937 rsurface.batchtvector3f_bufferoffset = 0;
7938 rsurface.batchnormal3f = NULL;
7939 rsurface.batchnormal3f_vertexbuffer = NULL;
7940 rsurface.batchnormal3f_bufferoffset = 0;
7941 rsurface.batchlightmapcolor4f = NULL;
7942 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7943 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7944 rsurface.batchtexcoordtexture2f = NULL;
7945 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7946 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7947 rsurface.batchtexcoordlightmap2f = NULL;
7948 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7949 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7950 rsurface.batchvertexmesh = NULL;
7951 rsurface.batchvertexmeshbuffer = NULL;
7952 rsurface.batchvertex3fbuffer = NULL;
7953 rsurface.batchelement3i = NULL;
7954 rsurface.batchelement3i_indexbuffer = NULL;
7955 rsurface.batchelement3i_bufferoffset = 0;
7956 rsurface.batchelement3s = NULL;
7957 rsurface.batchelement3s_indexbuffer = NULL;
7958 rsurface.batchelement3s_bufferoffset = 0;
7959 rsurface.passcolor4f = NULL;
7960 rsurface.passcolor4f_vertexbuffer = NULL;
7961 rsurface.passcolor4f_bufferoffset = 0;
7963 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7965 if ((wantnormals || wanttangents) && !normal3f)
7967 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7968 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7970 if (wanttangents && !svector3f)
7972 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7973 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7974 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7979 float RSurf_FogPoint(const float *v)
7981 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7982 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7983 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7984 float FogHeightFade = r_refdef.fogheightfade;
7986 unsigned int fogmasktableindex;
7987 if (r_refdef.fogplaneviewabove)
7988 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7990 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7991 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7992 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7995 float RSurf_FogVertex(const float *v)
7997 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7998 float FogPlaneViewDist = rsurface.fogplaneviewdist;
7999 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8000 float FogHeightFade = rsurface.fogheightfade;
8002 unsigned int fogmasktableindex;
8003 if (r_refdef.fogplaneviewabove)
8004 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8006 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8007 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8008 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8011 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8014 for (i = 0;i < numelements;i++)
8015 outelement3i[i] = inelement3i[i] + adjust;
8018 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8019 extern cvar_t gl_vbo;
8020 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8028 int surfacefirsttriangle;
8029 int surfacenumtriangles;
8030 int surfacefirstvertex;
8031 int surfaceendvertex;
8032 int surfacenumvertices;
8033 int batchnumvertices;
8034 int batchnumtriangles;
8038 qboolean dynamicvertex;
8042 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8044 q3shaderinfo_deform_t *deform;
8045 const msurface_t *surface, *firstsurface;
8046 r_vertexmesh_t *vertexmesh;
8047 if (!texturenumsurfaces)
8049 // find vertex range of this surface batch
8051 firstsurface = texturesurfacelist[0];
8052 firsttriangle = firstsurface->num_firsttriangle;
8053 batchnumvertices = 0;
8054 batchnumtriangles = 0;
8055 firstvertex = endvertex = firstsurface->num_firstvertex;
8056 for (i = 0;i < texturenumsurfaces;i++)
8058 surface = texturesurfacelist[i];
8059 if (surface != firstsurface + i)
8061 surfacefirstvertex = surface->num_firstvertex;
8062 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8063 surfacenumvertices = surface->num_vertices;
8064 surfacenumtriangles = surface->num_triangles;
8065 if (firstvertex > surfacefirstvertex)
8066 firstvertex = surfacefirstvertex;
8067 if (endvertex < surfaceendvertex)
8068 endvertex = surfaceendvertex;
8069 batchnumvertices += surfacenumvertices;
8070 batchnumtriangles += surfacenumtriangles;
8073 // we now know the vertex range used, and if there are any gaps in it
8074 rsurface.batchfirstvertex = firstvertex;
8075 rsurface.batchnumvertices = endvertex - firstvertex;
8076 rsurface.batchfirsttriangle = firsttriangle;
8077 rsurface.batchnumtriangles = batchnumtriangles;
8079 // this variable holds flags for which properties have been updated that
8080 // may require regenerating vertexmesh array...
8083 // check if any dynamic vertex processing must occur
8084 dynamicvertex = false;
8086 // if there is a chance of animated vertex colors, it's a dynamic batch
8087 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8089 dynamicvertex = true;
8090 batchneed |= BATCHNEED_NOGAPS;
8091 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8094 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8096 switch (deform->deform)
8099 case Q3DEFORM_PROJECTIONSHADOW:
8100 case Q3DEFORM_TEXT0:
8101 case Q3DEFORM_TEXT1:
8102 case Q3DEFORM_TEXT2:
8103 case Q3DEFORM_TEXT3:
8104 case Q3DEFORM_TEXT4:
8105 case Q3DEFORM_TEXT5:
8106 case Q3DEFORM_TEXT6:
8107 case Q3DEFORM_TEXT7:
8110 case Q3DEFORM_AUTOSPRITE:
8111 dynamicvertex = true;
8112 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8113 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8115 case Q3DEFORM_AUTOSPRITE2:
8116 dynamicvertex = true;
8117 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8118 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8120 case Q3DEFORM_NORMAL:
8121 dynamicvertex = true;
8122 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8123 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8126 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8127 break; // if wavefunc is a nop, ignore this transform
8128 dynamicvertex = true;
8129 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8130 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8132 case Q3DEFORM_BULGE:
8133 dynamicvertex = true;
8134 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8135 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8138 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8139 break; // if wavefunc is a nop, ignore this transform
8140 dynamicvertex = true;
8141 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8142 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8146 switch(rsurface.texture->tcgen.tcgen)
8149 case Q3TCGEN_TEXTURE:
8151 case Q3TCGEN_LIGHTMAP:
8152 dynamicvertex = true;
8153 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8154 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8156 case Q3TCGEN_VECTOR:
8157 dynamicvertex = true;
8158 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8159 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8161 case Q3TCGEN_ENVIRONMENT:
8162 dynamicvertex = true;
8163 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8164 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8167 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8169 dynamicvertex = true;
8170 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8171 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8174 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8176 dynamicvertex = true;
8177 batchneed |= BATCHNEED_NOGAPS;
8178 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8181 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8183 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8184 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8185 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8186 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8187 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8188 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8189 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8192 // when the model data has no vertex buffer (dynamic mesh), we need to
8194 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8195 batchneed |= BATCHNEED_NOGAPS;
8197 // if needsupdate, we have to do a dynamic vertex batch for sure
8198 if (needsupdate & batchneed)
8199 dynamicvertex = true;
8201 // see if we need to build vertexmesh from arrays
8202 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8203 dynamicvertex = true;
8205 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8206 // also some drivers strongly dislike firstvertex
8207 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8208 dynamicvertex = true;
8210 rsurface.batchvertex3f = rsurface.modelvertex3f;
8211 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8212 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8213 rsurface.batchsvector3f = rsurface.modelsvector3f;
8214 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8215 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8216 rsurface.batchtvector3f = rsurface.modeltvector3f;
8217 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8218 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8219 rsurface.batchnormal3f = rsurface.modelnormal3f;
8220 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8221 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8222 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8223 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8224 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8225 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8226 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8227 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8228 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8229 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8230 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8231 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8232 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8233 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8234 rsurface.batchelement3i = rsurface.modelelement3i;
8235 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8236 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8237 rsurface.batchelement3s = rsurface.modelelement3s;
8238 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8239 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8241 // if any dynamic vertex processing has to occur in software, we copy the
8242 // entire surface list together before processing to rebase the vertices
8243 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8245 // if any gaps exist and we do not have a static vertex buffer, we have to
8246 // copy the surface list together to avoid wasting upload bandwidth on the
8247 // vertices in the gaps.
8249 // if gaps exist and we have a static vertex buffer, we still have to
8250 // combine the index buffer ranges into one dynamic index buffer.
8252 // in all cases we end up with data that can be drawn in one call.
8256 // static vertex data, just set pointers...
8257 rsurface.batchgeneratedvertex = false;
8258 // if there are gaps, we want to build a combined index buffer,
8259 // otherwise use the original static buffer with an appropriate offset
8262 // build a new triangle elements array for this batch
8263 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8264 rsurface.batchfirsttriangle = 0;
8266 for (i = 0;i < texturenumsurfaces;i++)
8268 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8269 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8270 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8271 numtriangles += surfacenumtriangles;
8273 rsurface.batchelement3i_indexbuffer = NULL;
8274 rsurface.batchelement3i_bufferoffset = 0;
8275 rsurface.batchelement3s = NULL;
8276 rsurface.batchelement3s_indexbuffer = NULL;
8277 rsurface.batchelement3s_bufferoffset = 0;
8278 if (endvertex <= 65536)
8280 // make a 16bit (unsigned short) index array if possible
8281 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8282 for (i = 0;i < numtriangles*3;i++)
8283 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8289 // something needs software processing, do it for real...
8290 // we only directly handle separate array data in this case and then
8291 // generate interleaved data if needed...
8292 rsurface.batchgeneratedvertex = true;
8294 // now copy the vertex data into a combined array and make an index array
8295 // (this is what Quake3 does all the time)
8296 //if (gaps || rsurface.batchfirstvertex)
8298 rsurface.batchvertex3fbuffer = NULL;
8299 rsurface.batchvertexmesh = NULL;
8300 rsurface.batchvertexmeshbuffer = NULL;
8301 rsurface.batchvertex3f = NULL;
8302 rsurface.batchvertex3f_vertexbuffer = NULL;
8303 rsurface.batchvertex3f_bufferoffset = 0;
8304 rsurface.batchsvector3f = NULL;
8305 rsurface.batchsvector3f_vertexbuffer = NULL;
8306 rsurface.batchsvector3f_bufferoffset = 0;
8307 rsurface.batchtvector3f = NULL;
8308 rsurface.batchtvector3f_vertexbuffer = NULL;
8309 rsurface.batchtvector3f_bufferoffset = 0;
8310 rsurface.batchnormal3f = NULL;
8311 rsurface.batchnormal3f_vertexbuffer = NULL;
8312 rsurface.batchnormal3f_bufferoffset = 0;
8313 rsurface.batchlightmapcolor4f = NULL;
8314 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8315 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8316 rsurface.batchtexcoordtexture2f = NULL;
8317 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8318 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8319 rsurface.batchtexcoordlightmap2f = NULL;
8320 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8321 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8322 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8323 rsurface.batchelement3i_indexbuffer = NULL;
8324 rsurface.batchelement3i_bufferoffset = 0;
8325 rsurface.batchelement3s = NULL;
8326 rsurface.batchelement3s_indexbuffer = NULL;
8327 rsurface.batchelement3s_bufferoffset = 0;
8328 // we'll only be setting up certain arrays as needed
8329 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8330 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8331 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8332 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8333 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8334 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8335 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8337 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8338 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8340 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8341 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8342 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8343 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8344 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8345 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8348 for (i = 0;i < texturenumsurfaces;i++)
8350 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8351 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8352 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8353 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8354 // copy only the data requested
8355 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8356 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8357 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8359 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8360 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8361 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8362 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8363 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8365 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8366 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8368 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8369 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8370 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8371 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8372 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8373 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8375 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8376 numvertices += surfacenumvertices;
8377 numtriangles += surfacenumtriangles;
8380 // generate a 16bit index array as well if possible
8381 // (in general, dynamic batches fit)
8382 if (numvertices <= 65536)
8384 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8385 for (i = 0;i < numtriangles*3;i++)
8386 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8389 // since we've copied everything, the batch now starts at 0
8390 rsurface.batchfirstvertex = 0;
8391 rsurface.batchnumvertices = batchnumvertices;
8392 rsurface.batchfirsttriangle = 0;
8393 rsurface.batchnumtriangles = batchnumtriangles;
8396 // q1bsp surfaces rendered in vertex color mode have to have colors
8397 // calculated based on lightstyles
8398 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8400 // generate color arrays for the surfaces in this list
8405 const unsigned char *lm;
8406 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8407 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8408 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8410 for (i = 0;i < texturenumsurfaces;i++)
8412 surface = texturesurfacelist[i];
8413 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8414 surfacenumvertices = surface->num_vertices;
8415 if (surface->lightmapinfo->samples)
8417 for (j = 0;j < surfacenumvertices;j++)
8419 lm = surface->lightmapinfo->samples + offsets[j];
8420 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8421 VectorScale(lm, scale, c);
8422 if (surface->lightmapinfo->styles[1] != 255)
8424 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8426 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8427 VectorMA(c, scale, lm, c);
8428 if (surface->lightmapinfo->styles[2] != 255)
8431 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8432 VectorMA(c, scale, lm, c);
8433 if (surface->lightmapinfo->styles[3] != 255)
8436 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8437 VectorMA(c, scale, lm, c);
8444 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);
8450 for (j = 0;j < surfacenumvertices;j++)
8452 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8459 // if vertices are deformed (sprite flares and things in maps, possibly
8460 // water waves, bulges and other deformations), modify the copied vertices
8462 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8464 switch (deform->deform)
8467 case Q3DEFORM_PROJECTIONSHADOW:
8468 case Q3DEFORM_TEXT0:
8469 case Q3DEFORM_TEXT1:
8470 case Q3DEFORM_TEXT2:
8471 case Q3DEFORM_TEXT3:
8472 case Q3DEFORM_TEXT4:
8473 case Q3DEFORM_TEXT5:
8474 case Q3DEFORM_TEXT6:
8475 case Q3DEFORM_TEXT7:
8478 case Q3DEFORM_AUTOSPRITE:
8479 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8480 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8481 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8482 VectorNormalize(newforward);
8483 VectorNormalize(newright);
8484 VectorNormalize(newup);
8485 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8486 // rsurface.batchvertex3f_vertexbuffer = NULL;
8487 // rsurface.batchvertex3f_bufferoffset = 0;
8488 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8489 // rsurface.batchsvector3f_vertexbuffer = NULL;
8490 // rsurface.batchsvector3f_bufferoffset = 0;
8491 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8492 // rsurface.batchtvector3f_vertexbuffer = NULL;
8493 // rsurface.batchtvector3f_bufferoffset = 0;
8494 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8495 // rsurface.batchnormal3f_vertexbuffer = NULL;
8496 // rsurface.batchnormal3f_bufferoffset = 0;
8497 // a single autosprite surface can contain multiple sprites...
8498 for (j = 0;j < batchnumvertices - 3;j += 4)
8500 VectorClear(center);
8501 for (i = 0;i < 4;i++)
8502 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8503 VectorScale(center, 0.25f, center);
8504 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8505 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8506 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8507 for (i = 0;i < 4;i++)
8509 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8510 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8513 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8514 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8515 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);
8517 case Q3DEFORM_AUTOSPRITE2:
8518 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8519 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8520 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8521 VectorNormalize(newforward);
8522 VectorNormalize(newright);
8523 VectorNormalize(newup);
8524 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8525 // rsurface.batchvertex3f_vertexbuffer = NULL;
8526 // rsurface.batchvertex3f_bufferoffset = 0;
8528 const float *v1, *v2;
8538 memset(shortest, 0, sizeof(shortest));
8539 // a single autosprite surface can contain multiple sprites...
8540 for (j = 0;j < batchnumvertices - 3;j += 4)
8542 VectorClear(center);
8543 for (i = 0;i < 4;i++)
8544 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8545 VectorScale(center, 0.25f, center);
8546 // find the two shortest edges, then use them to define the
8547 // axis vectors for rotating around the central axis
8548 for (i = 0;i < 6;i++)
8550 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8551 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8552 l = VectorDistance2(v1, v2);
8553 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8555 l += (1.0f / 1024.0f);
8556 if (shortest[0].length2 > l || i == 0)
8558 shortest[1] = shortest[0];
8559 shortest[0].length2 = l;
8560 shortest[0].v1 = v1;
8561 shortest[0].v2 = v2;
8563 else if (shortest[1].length2 > l || i == 1)
8565 shortest[1].length2 = l;
8566 shortest[1].v1 = v1;
8567 shortest[1].v2 = v2;
8570 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8571 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8572 // this calculates the right vector from the shortest edge
8573 // and the up vector from the edge midpoints
8574 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8575 VectorNormalize(right);
8576 VectorSubtract(end, start, up);
8577 VectorNormalize(up);
8578 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8579 VectorSubtract(rsurface.localvieworigin, center, forward);
8580 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8581 VectorNegate(forward, forward);
8582 VectorReflect(forward, 0, up, forward);
8583 VectorNormalize(forward);
8584 CrossProduct(up, forward, newright);
8585 VectorNormalize(newright);
8586 // rotate the quad around the up axis vector, this is made
8587 // especially easy by the fact we know the quad is flat,
8588 // so we only have to subtract the center position and
8589 // measure distance along the right vector, and then
8590 // multiply that by the newright vector and add back the
8592 // we also need to subtract the old position to undo the
8593 // displacement from the center, which we do with a
8594 // DotProduct, the subtraction/addition of center is also
8595 // optimized into DotProducts here
8596 l = DotProduct(right, center);
8597 for (i = 0;i < 4;i++)
8599 v1 = rsurface.batchvertex3f + 3*(j+i);
8600 f = DotProduct(right, v1) - l;
8601 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8605 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8607 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8608 // rsurface.batchnormal3f_vertexbuffer = NULL;
8609 // rsurface.batchnormal3f_bufferoffset = 0;
8610 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8612 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8614 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8615 // rsurface.batchsvector3f_vertexbuffer = NULL;
8616 // rsurface.batchsvector3f_bufferoffset = 0;
8617 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8618 // rsurface.batchtvector3f_vertexbuffer = NULL;
8619 // rsurface.batchtvector3f_bufferoffset = 0;
8620 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);
8623 case Q3DEFORM_NORMAL:
8624 // deform the normals to make reflections wavey
8625 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8626 rsurface.batchnormal3f_vertexbuffer = NULL;
8627 rsurface.batchnormal3f_bufferoffset = 0;
8628 for (j = 0;j < batchnumvertices;j++)
8631 float *normal = rsurface.batchnormal3f + 3*j;
8632 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8633 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8634 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]);
8635 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]);
8636 VectorNormalize(normal);
8638 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8640 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8641 // rsurface.batchsvector3f_vertexbuffer = NULL;
8642 // rsurface.batchsvector3f_bufferoffset = 0;
8643 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8644 // rsurface.batchtvector3f_vertexbuffer = NULL;
8645 // rsurface.batchtvector3f_bufferoffset = 0;
8646 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);
8650 // deform vertex array to make wavey water and flags and such
8651 waveparms[0] = deform->waveparms[0];
8652 waveparms[1] = deform->waveparms[1];
8653 waveparms[2] = deform->waveparms[2];
8654 waveparms[3] = deform->waveparms[3];
8655 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8656 break; // if wavefunc is a nop, don't make a dynamic vertex array
8657 // this is how a divisor of vertex influence on deformation
8658 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8659 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8660 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8661 // rsurface.batchvertex3f_vertexbuffer = NULL;
8662 // rsurface.batchvertex3f_bufferoffset = 0;
8663 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8664 // rsurface.batchnormal3f_vertexbuffer = NULL;
8665 // rsurface.batchnormal3f_bufferoffset = 0;
8666 for (j = 0;j < batchnumvertices;j++)
8668 // if the wavefunc depends on time, evaluate it per-vertex
8671 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8672 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8674 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8676 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8677 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8678 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8680 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8681 // rsurface.batchsvector3f_vertexbuffer = NULL;
8682 // rsurface.batchsvector3f_bufferoffset = 0;
8683 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8684 // rsurface.batchtvector3f_vertexbuffer = NULL;
8685 // rsurface.batchtvector3f_bufferoffset = 0;
8686 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);
8689 case Q3DEFORM_BULGE:
8690 // deform vertex array to make the surface have moving bulges
8691 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8692 // rsurface.batchvertex3f_vertexbuffer = NULL;
8693 // rsurface.batchvertex3f_bufferoffset = 0;
8694 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8695 // rsurface.batchnormal3f_vertexbuffer = NULL;
8696 // rsurface.batchnormal3f_bufferoffset = 0;
8697 for (j = 0;j < batchnumvertices;j++)
8699 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8700 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8702 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8703 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8704 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8706 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8707 // rsurface.batchsvector3f_vertexbuffer = NULL;
8708 // rsurface.batchsvector3f_bufferoffset = 0;
8709 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8710 // rsurface.batchtvector3f_vertexbuffer = NULL;
8711 // rsurface.batchtvector3f_bufferoffset = 0;
8712 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);
8716 // deform vertex array
8717 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8718 break; // if wavefunc is a nop, don't make a dynamic vertex array
8719 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8720 VectorScale(deform->parms, scale, waveparms);
8721 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8722 // rsurface.batchvertex3f_vertexbuffer = NULL;
8723 // rsurface.batchvertex3f_bufferoffset = 0;
8724 for (j = 0;j < batchnumvertices;j++)
8725 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8730 // generate texcoords based on the chosen texcoord source
8731 switch(rsurface.texture->tcgen.tcgen)
8734 case Q3TCGEN_TEXTURE:
8736 case Q3TCGEN_LIGHTMAP:
8737 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8738 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8739 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8740 if (rsurface.batchtexcoordlightmap2f)
8741 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8743 case Q3TCGEN_VECTOR:
8744 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8745 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8746 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8747 for (j = 0;j < batchnumvertices;j++)
8749 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8750 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8753 case Q3TCGEN_ENVIRONMENT:
8754 // make environment reflections using a spheremap
8755 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8756 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8757 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8758 for (j = 0;j < batchnumvertices;j++)
8760 // identical to Q3A's method, but executed in worldspace so
8761 // carried models can be shiny too
8763 float viewer[3], d, reflected[3], worldreflected[3];
8765 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8766 // VectorNormalize(viewer);
8768 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8770 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8771 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8772 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8773 // note: this is proportinal to viewer, so we can normalize later
8775 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8776 VectorNormalize(worldreflected);
8778 // note: this sphere map only uses world x and z!
8779 // so positive and negative y will LOOK THE SAME.
8780 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8781 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8785 // the only tcmod that needs software vertex processing is turbulent, so
8786 // check for it here and apply the changes if needed
8787 // and we only support that as the first one
8788 // (handling a mixture of turbulent and other tcmods would be problematic
8789 // without punting it entirely to a software path)
8790 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8792 amplitude = rsurface.texture->tcmods[0].parms[1];
8793 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8794 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8795 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8796 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8797 for (j = 0;j < batchnumvertices;j++)
8799 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);
8800 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8804 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8806 // convert the modified arrays to vertex structs
8807 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8808 // rsurface.batchvertexmeshbuffer = NULL;
8809 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8810 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8811 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8812 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8813 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8814 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8815 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8817 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8819 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8820 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8823 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8824 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8825 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8826 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8827 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8828 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8829 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8830 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8831 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8835 void RSurf_DrawBatch(void)
8837 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8838 // through the pipeline, killing it earlier in the pipeline would have
8839 // per-surface overhead rather than per-batch overhead, so it's best to
8840 // reject it here, before it hits glDraw.
8841 if (rsurface.batchnumtriangles == 0)
8844 // batch debugging code
8845 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8851 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8852 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8855 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8857 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8859 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8860 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);
8867 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);
8870 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8872 // pick the closest matching water plane
8873 int planeindex, vertexindex, bestplaneindex = -1;
8877 r_waterstate_waterplane_t *p;
8878 qboolean prepared = false;
8880 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8882 if(p->camera_entity != rsurface.texture->camera_entity)
8887 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8889 if(rsurface.batchnumvertices == 0)
8892 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8894 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8895 d += fabs(PlaneDiff(vert, &p->plane));
8897 if (bestd > d || bestplaneindex < 0)
8900 bestplaneindex = planeindex;
8903 return bestplaneindex;
8904 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8905 // this situation though, as it might be better to render single larger
8906 // batches with useless stuff (backface culled for example) than to
8907 // render multiple smaller batches
8910 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8913 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8914 rsurface.passcolor4f_vertexbuffer = 0;
8915 rsurface.passcolor4f_bufferoffset = 0;
8916 for (i = 0;i < rsurface.batchnumvertices;i++)
8917 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8920 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8927 if (rsurface.passcolor4f)
8929 // generate color arrays
8930 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8931 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8932 rsurface.passcolor4f_vertexbuffer = 0;
8933 rsurface.passcolor4f_bufferoffset = 0;
8934 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)
8936 f = RSurf_FogVertex(v);
8945 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8946 rsurface.passcolor4f_vertexbuffer = 0;
8947 rsurface.passcolor4f_bufferoffset = 0;
8948 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8950 f = RSurf_FogVertex(v);
8959 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8966 if (!rsurface.passcolor4f)
8968 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8969 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8970 rsurface.passcolor4f_vertexbuffer = 0;
8971 rsurface.passcolor4f_bufferoffset = 0;
8972 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)
8974 f = RSurf_FogVertex(v);
8975 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8976 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8977 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8982 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8987 if (!rsurface.passcolor4f)
8989 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8990 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8991 rsurface.passcolor4f_vertexbuffer = 0;
8992 rsurface.passcolor4f_bufferoffset = 0;
8993 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9002 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9007 if (!rsurface.passcolor4f)
9009 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9010 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9011 rsurface.passcolor4f_vertexbuffer = 0;
9012 rsurface.passcolor4f_bufferoffset = 0;
9013 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9015 c2[0] = c[0] + r_refdef.scene.ambient;
9016 c2[1] = c[1] + r_refdef.scene.ambient;
9017 c2[2] = c[2] + r_refdef.scene.ambient;
9022 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9025 rsurface.passcolor4f = NULL;
9026 rsurface.passcolor4f_vertexbuffer = 0;
9027 rsurface.passcolor4f_bufferoffset = 0;
9028 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9029 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9030 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9031 GL_Color(r, g, b, a);
9032 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9036 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9038 // TODO: optimize applyfog && applycolor case
9039 // just apply fog if necessary, and tint the fog color array if necessary
9040 rsurface.passcolor4f = NULL;
9041 rsurface.passcolor4f_vertexbuffer = 0;
9042 rsurface.passcolor4f_bufferoffset = 0;
9043 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9044 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9045 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9046 GL_Color(r, g, b, a);
9050 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9053 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9054 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9055 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9056 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9057 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9058 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9059 GL_Color(r, g, b, a);
9063 static void RSurf_DrawBatch_GL11_ClampColor(void)
9068 if (!rsurface.passcolor4f)
9070 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9072 c2[0] = bound(0.0f, c1[0], 1.0f);
9073 c2[1] = bound(0.0f, c1[1], 1.0f);
9074 c2[2] = bound(0.0f, c1[2], 1.0f);
9075 c2[3] = bound(0.0f, c1[3], 1.0f);
9079 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9089 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9090 rsurface.passcolor4f_vertexbuffer = 0;
9091 rsurface.passcolor4f_bufferoffset = 0;
9092 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)
9094 f = -DotProduct(r_refdef.view.forward, n);
9096 f = f * 0.85 + 0.15; // work around so stuff won't get black
9097 f *= r_refdef.lightmapintensity;
9098 Vector4Set(c, f, f, f, 1);
9102 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9104 RSurf_DrawBatch_GL11_ApplyFakeLight();
9105 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9106 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9107 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9108 GL_Color(r, g, b, a);
9112 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9120 vec3_t ambientcolor;
9121 vec3_t diffusecolor;
9125 VectorCopy(rsurface.modellight_lightdir, lightdir);
9126 f = 0.5f * r_refdef.lightmapintensity;
9127 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9128 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9129 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9130 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9131 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9132 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9134 if (VectorLength2(diffusecolor) > 0)
9136 // q3-style directional shading
9137 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9138 rsurface.passcolor4f_vertexbuffer = 0;
9139 rsurface.passcolor4f_bufferoffset = 0;
9140 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)
9142 if ((f = DotProduct(n, lightdir)) > 0)
9143 VectorMA(ambientcolor, f, diffusecolor, c);
9145 VectorCopy(ambientcolor, c);
9152 *applycolor = false;
9156 *r = ambientcolor[0];
9157 *g = ambientcolor[1];
9158 *b = ambientcolor[2];
9159 rsurface.passcolor4f = NULL;
9160 rsurface.passcolor4f_vertexbuffer = 0;
9161 rsurface.passcolor4f_bufferoffset = 0;
9165 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9167 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9168 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9169 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9170 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9171 GL_Color(r, g, b, a);
9175 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9181 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9183 f = 1 - RSurf_FogVertex(v);
9191 void RSurf_SetupDepthAndCulling(void)
9193 // submodels are biased to avoid z-fighting with world surfaces that they
9194 // may be exactly overlapping (avoids z-fighting artifacts on certain
9195 // doors and things in Quake maps)
9196 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9197 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9198 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9199 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9202 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9204 // transparent sky would be ridiculous
9205 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9207 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9208 skyrenderlater = true;
9209 RSurf_SetupDepthAndCulling();
9211 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9212 // skymasking on them, and Quake3 never did sky masking (unlike
9213 // software Quake and software Quake2), so disable the sky masking
9214 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9215 // and skymasking also looks very bad when noclipping outside the
9216 // level, so don't use it then either.
9217 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9219 R_Mesh_ResetTextureState();
9220 if (skyrendermasked)
9222 R_SetupShader_DepthOrShadow();
9223 // depth-only (masking)
9224 GL_ColorMask(0,0,0,0);
9225 // just to make sure that braindead drivers don't draw
9226 // anything despite that colormask...
9227 GL_BlendFunc(GL_ZERO, GL_ONE);
9228 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9229 if (rsurface.batchvertex3fbuffer)
9230 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9232 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9236 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9238 GL_BlendFunc(GL_ONE, GL_ZERO);
9239 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9240 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9241 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9244 if (skyrendermasked)
9245 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9247 R_Mesh_ResetTextureState();
9248 GL_Color(1, 1, 1, 1);
9251 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9252 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9253 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9255 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9259 // render screenspace normalmap to texture
9261 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9266 // bind lightmap texture
9268 // water/refraction/reflection/camera surfaces have to be handled specially
9269 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9271 int start, end, startplaneindex;
9272 for (start = 0;start < texturenumsurfaces;start = end)
9274 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9275 if(startplaneindex < 0)
9277 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9278 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9282 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9284 // now that we have a batch using the same planeindex, render it
9285 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9287 // render water or distortion background
9289 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));
9291 // blend surface on top
9292 GL_DepthMask(false);
9293 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9296 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9298 // render surface with reflection texture as input
9299 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9300 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));
9307 // render surface batch normally
9308 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9309 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9313 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9315 // OpenGL 1.3 path - anything not completely ancient
9316 qboolean applycolor;
9319 const texturelayer_t *layer;
9320 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);
9321 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9323 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9326 int layertexrgbscale;
9327 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9329 if (layerindex == 0)
9333 GL_AlphaTest(false);
9334 GL_DepthFunc(GL_EQUAL);
9337 GL_DepthMask(layer->depthmask && writedepth);
9338 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9339 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9341 layertexrgbscale = 4;
9342 VectorScale(layer->color, 0.25f, layercolor);
9344 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9346 layertexrgbscale = 2;
9347 VectorScale(layer->color, 0.5f, layercolor);
9351 layertexrgbscale = 1;
9352 VectorScale(layer->color, 1.0f, layercolor);
9354 layercolor[3] = layer->color[3];
9355 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9356 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9357 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9358 switch (layer->type)
9360 case TEXTURELAYERTYPE_LITTEXTURE:
9361 // single-pass lightmapped texture with 2x rgbscale
9362 R_Mesh_TexBind(0, r_texture_white);
9363 R_Mesh_TexMatrix(0, NULL);
9364 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9365 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9366 R_Mesh_TexBind(1, layer->texture);
9367 R_Mesh_TexMatrix(1, &layer->texmatrix);
9368 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9369 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9370 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9371 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9372 else if (FAKELIGHT_ENABLED)
9373 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9374 else if (rsurface.uselightmaptexture)
9375 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9377 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9379 case TEXTURELAYERTYPE_TEXTURE:
9380 // singletexture unlit texture with transparency support
9381 R_Mesh_TexBind(0, layer->texture);
9382 R_Mesh_TexMatrix(0, &layer->texmatrix);
9383 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9384 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9385 R_Mesh_TexBind(1, 0);
9386 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9387 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9389 case TEXTURELAYERTYPE_FOG:
9390 // singletexture fogging
9393 R_Mesh_TexBind(0, layer->texture);
9394 R_Mesh_TexMatrix(0, &layer->texmatrix);
9395 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9396 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9400 R_Mesh_TexBind(0, 0);
9401 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9403 R_Mesh_TexBind(1, 0);
9404 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9405 // generate a color array for the fog pass
9406 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9407 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9411 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9414 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9416 GL_DepthFunc(GL_LEQUAL);
9417 GL_AlphaTest(false);
9421 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9423 // OpenGL 1.1 - crusty old voodoo path
9426 const texturelayer_t *layer;
9427 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);
9428 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9430 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9432 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9434 if (layerindex == 0)
9438 GL_AlphaTest(false);
9439 GL_DepthFunc(GL_EQUAL);
9442 GL_DepthMask(layer->depthmask && writedepth);
9443 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9444 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9445 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9446 switch (layer->type)
9448 case TEXTURELAYERTYPE_LITTEXTURE:
9449 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9451 // two-pass lit texture with 2x rgbscale
9452 // first the lightmap pass
9453 R_Mesh_TexBind(0, r_texture_white);
9454 R_Mesh_TexMatrix(0, NULL);
9455 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9456 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9457 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9458 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9459 else if (FAKELIGHT_ENABLED)
9460 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9461 else if (rsurface.uselightmaptexture)
9462 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9464 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9465 // then apply the texture to it
9466 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9467 R_Mesh_TexBind(0, layer->texture);
9468 R_Mesh_TexMatrix(0, &layer->texmatrix);
9469 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9470 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9471 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);
9475 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9476 R_Mesh_TexBind(0, layer->texture);
9477 R_Mesh_TexMatrix(0, &layer->texmatrix);
9478 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9479 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9480 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9481 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);
9483 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);
9486 case TEXTURELAYERTYPE_TEXTURE:
9487 // singletexture unlit texture with transparency support
9488 R_Mesh_TexBind(0, layer->texture);
9489 R_Mesh_TexMatrix(0, &layer->texmatrix);
9490 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9491 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9492 RSurf_DrawBatch_GL11_Unlit(layer->color[0], 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);
9494 case TEXTURELAYERTYPE_FOG:
9495 // singletexture fogging
9498 R_Mesh_TexBind(0, layer->texture);
9499 R_Mesh_TexMatrix(0, &layer->texmatrix);
9500 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9501 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9505 R_Mesh_TexBind(0, 0);
9506 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9508 // generate a color array for the fog pass
9509 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9510 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9514 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9517 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9519 GL_DepthFunc(GL_LEQUAL);
9520 GL_AlphaTest(false);
9524 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9528 r_vertexgeneric_t *batchvertex;
9531 // R_Mesh_ResetTextureState();
9532 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9534 if(rsurface.texture && rsurface.texture->currentskinframe)
9536 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9537 c[3] *= rsurface.texture->currentalpha;
9547 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9549 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9550 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9551 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9554 // brighten it up (as texture value 127 means "unlit")
9555 c[0] *= 2 * r_refdef.view.colorscale;
9556 c[1] *= 2 * r_refdef.view.colorscale;
9557 c[2] *= 2 * r_refdef.view.colorscale;
9559 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9560 c[3] *= r_wateralpha.value;
9562 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9564 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9565 GL_DepthMask(false);
9567 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9569 GL_BlendFunc(GL_ONE, GL_ONE);
9570 GL_DepthMask(false);
9572 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9574 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9575 GL_DepthMask(false);
9577 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9579 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9580 GL_DepthMask(false);
9584 GL_BlendFunc(GL_ONE, GL_ZERO);
9585 GL_DepthMask(writedepth);
9588 if (r_showsurfaces.integer == 3)
9590 rsurface.passcolor4f = NULL;
9592 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9594 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9596 rsurface.passcolor4f = NULL;
9597 rsurface.passcolor4f_vertexbuffer = 0;
9598 rsurface.passcolor4f_bufferoffset = 0;
9600 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9602 qboolean applycolor = true;
9605 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9607 r_refdef.lightmapintensity = 1;
9608 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9609 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9611 else if (FAKELIGHT_ENABLED)
9613 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9615 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9616 RSurf_DrawBatch_GL11_ApplyFakeLight();
9617 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9621 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9623 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9624 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9625 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9628 if(!rsurface.passcolor4f)
9629 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9631 RSurf_DrawBatch_GL11_ApplyAmbient();
9632 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9633 if(r_refdef.fogenabled)
9634 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9635 RSurf_DrawBatch_GL11_ClampColor();
9637 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9638 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9641 else if (!r_refdef.view.showdebug)
9643 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9644 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9645 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9647 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9648 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9650 R_Mesh_PrepareVertices_Generic_Unlock();
9653 else if (r_showsurfaces.integer == 4)
9655 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9656 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9657 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9659 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9660 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9661 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9663 R_Mesh_PrepareVertices_Generic_Unlock();
9666 else if (r_showsurfaces.integer == 2)
9669 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9670 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9671 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9673 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9674 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9675 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9676 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9677 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9678 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9679 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9681 R_Mesh_PrepareVertices_Generic_Unlock();
9682 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9686 int texturesurfaceindex;
9688 const msurface_t *surface;
9689 float surfacecolor4f[4];
9690 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9691 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9693 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9695 surface = texturesurfacelist[texturesurfaceindex];
9696 k = (int)(((size_t)surface) / sizeof(msurface_t));
9697 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9698 for (j = 0;j < surface->num_vertices;j++)
9700 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9701 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9705 R_Mesh_PrepareVertices_Generic_Unlock();
9710 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9713 RSurf_SetupDepthAndCulling();
9714 if (r_showsurfaces.integer)
9716 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9719 switch (vid.renderpath)
9721 case RENDERPATH_GL20:
9722 case RENDERPATH_D3D9:
9723 case RENDERPATH_D3D10:
9724 case RENDERPATH_D3D11:
9725 case RENDERPATH_SOFT:
9726 case RENDERPATH_GLES2:
9727 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9729 case RENDERPATH_GL13:
9730 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9732 case RENDERPATH_GL11:
9733 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9739 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9742 RSurf_SetupDepthAndCulling();
9743 if (r_showsurfaces.integer)
9745 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9748 switch (vid.renderpath)
9750 case RENDERPATH_GL20:
9751 case RENDERPATH_D3D9:
9752 case RENDERPATH_D3D10:
9753 case RENDERPATH_D3D11:
9754 case RENDERPATH_SOFT:
9755 case RENDERPATH_GLES2:
9756 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9758 case RENDERPATH_GL13:
9759 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9761 case RENDERPATH_GL11:
9762 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9768 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9771 int texturenumsurfaces, endsurface;
9773 const msurface_t *surface;
9774 #define MAXBATCH_TRANSPARENTSURFACES 256
9775 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9777 // if the model is static it doesn't matter what value we give for
9778 // wantnormals and wanttangents, so this logic uses only rules applicable
9779 // to a model, knowing that they are meaningless otherwise
9780 if (ent == r_refdef.scene.worldentity)
9781 RSurf_ActiveWorldEntity();
9782 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9783 RSurf_ActiveModelEntity(ent, false, false, false);
9786 switch (vid.renderpath)
9788 case RENDERPATH_GL20:
9789 case RENDERPATH_D3D9:
9790 case RENDERPATH_D3D10:
9791 case RENDERPATH_D3D11:
9792 case RENDERPATH_SOFT:
9793 case RENDERPATH_GLES2:
9794 RSurf_ActiveModelEntity(ent, true, true, false);
9796 case RENDERPATH_GL13:
9797 case RENDERPATH_GL11:
9798 RSurf_ActiveModelEntity(ent, true, false, false);
9803 if (r_transparentdepthmasking.integer)
9805 qboolean setup = false;
9806 for (i = 0;i < numsurfaces;i = j)
9809 surface = rsurface.modelsurfaces + surfacelist[i];
9810 texture = surface->texture;
9811 rsurface.texture = R_GetCurrentTexture(texture);
9812 rsurface.lightmaptexture = NULL;
9813 rsurface.deluxemaptexture = NULL;
9814 rsurface.uselightmaptexture = false;
9815 // scan ahead until we find a different texture
9816 endsurface = min(i + 1024, numsurfaces);
9817 texturenumsurfaces = 0;
9818 texturesurfacelist[texturenumsurfaces++] = surface;
9819 for (;j < endsurface;j++)
9821 surface = rsurface.modelsurfaces + surfacelist[j];
9822 if (texture != surface->texture)
9824 texturesurfacelist[texturenumsurfaces++] = surface;
9826 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9828 // render the range of surfaces as depth
9832 GL_ColorMask(0,0,0,0);
9835 GL_BlendFunc(GL_ONE, GL_ZERO);
9837 // R_Mesh_ResetTextureState();
9838 R_SetupShader_DepthOrShadow();
9840 RSurf_SetupDepthAndCulling();
9841 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9842 if (rsurface.batchvertex3fbuffer)
9843 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9845 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9849 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9852 for (i = 0;i < numsurfaces;i = j)
9855 surface = rsurface.modelsurfaces + surfacelist[i];
9856 texture = surface->texture;
9857 rsurface.texture = R_GetCurrentTexture(texture);
9858 // scan ahead until we find a different texture
9859 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9860 texturenumsurfaces = 0;
9861 texturesurfacelist[texturenumsurfaces++] = surface;
9862 if(FAKELIGHT_ENABLED)
9864 rsurface.lightmaptexture = NULL;
9865 rsurface.deluxemaptexture = NULL;
9866 rsurface.uselightmaptexture = false;
9867 for (;j < endsurface;j++)
9869 surface = rsurface.modelsurfaces + surfacelist[j];
9870 if (texture != surface->texture)
9872 texturesurfacelist[texturenumsurfaces++] = surface;
9877 rsurface.lightmaptexture = surface->lightmaptexture;
9878 rsurface.deluxemaptexture = surface->deluxemaptexture;
9879 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9880 for (;j < endsurface;j++)
9882 surface = rsurface.modelsurfaces + surfacelist[j];
9883 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9885 texturesurfacelist[texturenumsurfaces++] = surface;
9888 // render the range of surfaces
9889 if (ent == r_refdef.scene.worldentity)
9890 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9892 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9894 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9897 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9899 // transparent surfaces get pushed off into the transparent queue
9900 int surfacelistindex;
9901 const msurface_t *surface;
9902 vec3_t tempcenter, center;
9903 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9905 surface = texturesurfacelist[surfacelistindex];
9906 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9907 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9908 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9909 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9910 if (queueentity->transparent_offset) // transparent offset
9912 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9913 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9914 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9916 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9920 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9922 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9924 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9926 RSurf_SetupDepthAndCulling();
9927 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9928 if (rsurface.batchvertex3fbuffer)
9929 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9931 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9935 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9937 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9940 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9943 if (!rsurface.texture->currentnumlayers)
9945 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9946 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9948 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9950 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9951 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9952 else if (!rsurface.texture->currentnumlayers)
9954 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9956 // in the deferred case, transparent surfaces were queued during prepass
9957 if (!r_shadow_usingdeferredprepass)
9958 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9962 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9963 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9968 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9972 R_FrameData_SetMark();
9973 // break the surface list down into batches by texture and use of lightmapping
9974 for (i = 0;i < numsurfaces;i = j)
9977 // texture is the base texture pointer, rsurface.texture is the
9978 // current frame/skin the texture is directing us to use (for example
9979 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9980 // use skin 1 instead)
9981 texture = surfacelist[i]->texture;
9982 rsurface.texture = R_GetCurrentTexture(texture);
9983 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9985 // if this texture is not the kind we want, skip ahead to the next one
9986 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9990 if(FAKELIGHT_ENABLED || depthonly || prepass)
9992 rsurface.lightmaptexture = NULL;
9993 rsurface.deluxemaptexture = NULL;
9994 rsurface.uselightmaptexture = false;
9995 // simply scan ahead until we find a different texture or lightmap state
9996 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10001 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10002 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10003 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10004 // simply scan ahead until we find a different texture or lightmap state
10005 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10008 // render the range of surfaces
10009 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10011 R_FrameData_ReturnToMark();
10014 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10018 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10021 if (!rsurface.texture->currentnumlayers)
10023 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10024 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10026 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10028 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10029 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10030 else if (!rsurface.texture->currentnumlayers)
10032 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10034 // in the deferred case, transparent surfaces were queued during prepass
10035 if (!r_shadow_usingdeferredprepass)
10036 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10040 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10041 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10046 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10049 texture_t *texture;
10050 R_FrameData_SetMark();
10051 // break the surface list down into batches by texture and use of lightmapping
10052 for (i = 0;i < numsurfaces;i = j)
10055 // texture is the base texture pointer, rsurface.texture is the
10056 // current frame/skin the texture is directing us to use (for example
10057 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10058 // use skin 1 instead)
10059 texture = surfacelist[i]->texture;
10060 rsurface.texture = R_GetCurrentTexture(texture);
10061 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10063 // if this texture is not the kind we want, skip ahead to the next one
10064 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10068 if(FAKELIGHT_ENABLED || depthonly || prepass)
10070 rsurface.lightmaptexture = NULL;
10071 rsurface.deluxemaptexture = NULL;
10072 rsurface.uselightmaptexture = false;
10073 // simply scan ahead until we find a different texture or lightmap state
10074 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10079 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10080 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10081 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10082 // simply scan ahead until we find a different texture or lightmap state
10083 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10086 // render the range of surfaces
10087 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10089 R_FrameData_ReturnToMark();
10092 float locboxvertex3f[6*4*3] =
10094 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10095 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10096 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10097 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10098 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10099 1,0,0, 0,0,0, 0,1,0, 1,1,0
10102 unsigned short locboxelements[6*2*3] =
10107 12,13,14, 12,14,15,
10108 16,17,18, 16,18,19,
10112 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10115 cl_locnode_t *loc = (cl_locnode_t *)ent;
10117 float vertex3f[6*4*3];
10119 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10120 GL_DepthMask(false);
10121 GL_DepthRange(0, 1);
10122 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10123 GL_DepthTest(true);
10124 GL_CullFace(GL_NONE);
10125 R_EntityMatrix(&identitymatrix);
10127 // R_Mesh_ResetTextureState();
10129 i = surfacelist[0];
10130 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10131 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10132 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10133 surfacelist[0] < 0 ? 0.5f : 0.125f);
10135 if (VectorCompare(loc->mins, loc->maxs))
10137 VectorSet(size, 2, 2, 2);
10138 VectorMA(loc->mins, -0.5f, size, mins);
10142 VectorCopy(loc->mins, mins);
10143 VectorSubtract(loc->maxs, loc->mins, size);
10146 for (i = 0;i < 6*4*3;)
10147 for (j = 0;j < 3;j++, i++)
10148 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10150 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10151 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10152 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10155 void R_DrawLocs(void)
10158 cl_locnode_t *loc, *nearestloc;
10160 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10161 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10163 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10164 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10168 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10170 if (decalsystem->decals)
10171 Mem_Free(decalsystem->decals);
10172 memset(decalsystem, 0, sizeof(*decalsystem));
10175 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)
10178 tridecal_t *decals;
10181 // expand or initialize the system
10182 if (decalsystem->maxdecals <= decalsystem->numdecals)
10184 decalsystem_t old = *decalsystem;
10185 qboolean useshortelements;
10186 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10187 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10188 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)));
10189 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10190 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10191 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10192 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10193 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10194 if (decalsystem->numdecals)
10195 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10197 Mem_Free(old.decals);
10198 for (i = 0;i < decalsystem->maxdecals*3;i++)
10199 decalsystem->element3i[i] = i;
10200 if (useshortelements)
10201 for (i = 0;i < decalsystem->maxdecals*3;i++)
10202 decalsystem->element3s[i] = i;
10205 // grab a decal and search for another free slot for the next one
10206 decals = decalsystem->decals;
10207 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10208 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10210 decalsystem->freedecal = i;
10211 if (decalsystem->numdecals <= i)
10212 decalsystem->numdecals = i + 1;
10214 // initialize the decal
10216 decal->triangleindex = triangleindex;
10217 decal->surfaceindex = surfaceindex;
10218 decal->decalsequence = decalsequence;
10219 decal->color4f[0][0] = c0[0];
10220 decal->color4f[0][1] = c0[1];
10221 decal->color4f[0][2] = c0[2];
10222 decal->color4f[0][3] = 1;
10223 decal->color4f[1][0] = c1[0];
10224 decal->color4f[1][1] = c1[1];
10225 decal->color4f[1][2] = c1[2];
10226 decal->color4f[1][3] = 1;
10227 decal->color4f[2][0] = c2[0];
10228 decal->color4f[2][1] = c2[1];
10229 decal->color4f[2][2] = c2[2];
10230 decal->color4f[2][3] = 1;
10231 decal->vertex3f[0][0] = v0[0];
10232 decal->vertex3f[0][1] = v0[1];
10233 decal->vertex3f[0][2] = v0[2];
10234 decal->vertex3f[1][0] = v1[0];
10235 decal->vertex3f[1][1] = v1[1];
10236 decal->vertex3f[1][2] = v1[2];
10237 decal->vertex3f[2][0] = v2[0];
10238 decal->vertex3f[2][1] = v2[1];
10239 decal->vertex3f[2][2] = v2[2];
10240 decal->texcoord2f[0][0] = t0[0];
10241 decal->texcoord2f[0][1] = t0[1];
10242 decal->texcoord2f[1][0] = t1[0];
10243 decal->texcoord2f[1][1] = t1[1];
10244 decal->texcoord2f[2][0] = t2[0];
10245 decal->texcoord2f[2][1] = t2[1];
10248 extern cvar_t cl_decals_bias;
10249 extern cvar_t cl_decals_models;
10250 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10251 // baseparms, parms, temps
10252 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)
10257 const float *vertex3f;
10258 const float *normal3f;
10260 float points[2][9][3];
10267 e = rsurface.modelelement3i + 3*triangleindex;
10269 vertex3f = rsurface.modelvertex3f;
10270 normal3f = rsurface.modelnormal3f;
10272 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10274 index = 3*e[cornerindex];
10275 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10278 //TriangleNormal(v[0], v[1], v[2], normal);
10279 //if (DotProduct(normal, localnormal) < 0.0f)
10281 // clip by each of the box planes formed from the projection matrix
10282 // if anything survives, we emit the decal
10283 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]);
10286 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]);
10289 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]);
10292 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]);
10295 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]);
10298 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]);
10301 // some part of the triangle survived, so we have to accept it...
10304 // dynamic always uses the original triangle
10306 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10308 index = 3*e[cornerindex];
10309 VectorCopy(vertex3f + index, v[cornerindex]);
10312 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10314 // convert vertex positions to texcoords
10315 Matrix4x4_Transform(projection, v[cornerindex], temp);
10316 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10317 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10318 // calculate distance fade from the projection origin
10319 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10320 f = bound(0.0f, f, 1.0f);
10321 c[cornerindex][0] = r * f;
10322 c[cornerindex][1] = g * f;
10323 c[cornerindex][2] = b * f;
10324 c[cornerindex][3] = 1.0f;
10325 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10328 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);
10330 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10331 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);
10333 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)
10335 matrix4x4_t projection;
10336 decalsystem_t *decalsystem;
10339 const msurface_t *surface;
10340 const msurface_t *surfaces;
10341 const int *surfacelist;
10342 const texture_t *texture;
10344 int numsurfacelist;
10345 int surfacelistindex;
10348 float localorigin[3];
10349 float localnormal[3];
10350 float localmins[3];
10351 float localmaxs[3];
10354 float planes[6][4];
10357 int bih_triangles_count;
10358 int bih_triangles[256];
10359 int bih_surfaces[256];
10361 decalsystem = &ent->decalsystem;
10362 model = ent->model;
10363 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10365 R_DecalSystem_Reset(&ent->decalsystem);
10369 if (!model->brush.data_leafs && !cl_decals_models.integer)
10371 if (decalsystem->model)
10372 R_DecalSystem_Reset(decalsystem);
10376 if (decalsystem->model != model)
10377 R_DecalSystem_Reset(decalsystem);
10378 decalsystem->model = model;
10380 RSurf_ActiveModelEntity(ent, true, false, false);
10382 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10383 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10384 VectorNormalize(localnormal);
10385 localsize = worldsize*rsurface.inversematrixscale;
10386 localmins[0] = localorigin[0] - localsize;
10387 localmins[1] = localorigin[1] - localsize;
10388 localmins[2] = localorigin[2] - localsize;
10389 localmaxs[0] = localorigin[0] + localsize;
10390 localmaxs[1] = localorigin[1] + localsize;
10391 localmaxs[2] = localorigin[2] + localsize;
10393 //VectorCopy(localnormal, planes[4]);
10394 //VectorVectors(planes[4], planes[2], planes[0]);
10395 AnglesFromVectors(angles, localnormal, NULL, false);
10396 AngleVectors(angles, planes[0], planes[2], planes[4]);
10397 VectorNegate(planes[0], planes[1]);
10398 VectorNegate(planes[2], planes[3]);
10399 VectorNegate(planes[4], planes[5]);
10400 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10401 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10402 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10403 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10404 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10405 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10410 matrix4x4_t forwardprojection;
10411 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10412 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10417 float projectionvector[4][3];
10418 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10419 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10420 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10421 projectionvector[0][0] = planes[0][0] * ilocalsize;
10422 projectionvector[0][1] = planes[1][0] * ilocalsize;
10423 projectionvector[0][2] = planes[2][0] * ilocalsize;
10424 projectionvector[1][0] = planes[0][1] * ilocalsize;
10425 projectionvector[1][1] = planes[1][1] * ilocalsize;
10426 projectionvector[1][2] = planes[2][1] * ilocalsize;
10427 projectionvector[2][0] = planes[0][2] * ilocalsize;
10428 projectionvector[2][1] = planes[1][2] * ilocalsize;
10429 projectionvector[2][2] = planes[2][2] * ilocalsize;
10430 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10431 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10432 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10433 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10437 dynamic = model->surfmesh.isanimated;
10438 numsurfacelist = model->nummodelsurfaces;
10439 surfacelist = model->sortedmodelsurfaces;
10440 surfaces = model->data_surfaces;
10443 bih_triangles_count = -1;
10446 if(model->render_bih.numleafs)
10447 bih = &model->render_bih;
10448 else if(model->collision_bih.numleafs)
10449 bih = &model->collision_bih;
10452 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10453 if(bih_triangles_count == 0)
10455 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10457 if(bih_triangles_count > 0)
10459 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10461 surfaceindex = bih_surfaces[triangleindex];
10462 surface = surfaces + surfaceindex;
10463 texture = surface->texture;
10464 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10466 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10468 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10473 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10475 surfaceindex = surfacelist[surfacelistindex];
10476 surface = surfaces + surfaceindex;
10477 // check cull box first because it rejects more than any other check
10478 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10480 // skip transparent surfaces
10481 texture = surface->texture;
10482 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10484 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10486 numtriangles = surface->num_triangles;
10487 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10488 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10493 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10494 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)
10496 int renderentityindex;
10497 float worldmins[3];
10498 float worldmaxs[3];
10499 entity_render_t *ent;
10501 if (!cl_decals_newsystem.integer)
10504 worldmins[0] = worldorigin[0] - worldsize;
10505 worldmins[1] = worldorigin[1] - worldsize;
10506 worldmins[2] = worldorigin[2] - worldsize;
10507 worldmaxs[0] = worldorigin[0] + worldsize;
10508 worldmaxs[1] = worldorigin[1] + worldsize;
10509 worldmaxs[2] = worldorigin[2] + worldsize;
10511 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10513 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10515 ent = r_refdef.scene.entities[renderentityindex];
10516 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10519 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10523 typedef struct r_decalsystem_splatqueue_s
10525 vec3_t worldorigin;
10526 vec3_t worldnormal;
10532 r_decalsystem_splatqueue_t;
10534 int r_decalsystem_numqueued = 0;
10535 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10537 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)
10539 r_decalsystem_splatqueue_t *queue;
10541 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10544 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10545 VectorCopy(worldorigin, queue->worldorigin);
10546 VectorCopy(worldnormal, queue->worldnormal);
10547 Vector4Set(queue->color, r, g, b, a);
10548 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10549 queue->worldsize = worldsize;
10550 queue->decalsequence = cl.decalsequence++;
10553 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10556 r_decalsystem_splatqueue_t *queue;
10558 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10559 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);
10560 r_decalsystem_numqueued = 0;
10563 extern cvar_t cl_decals_max;
10564 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10567 decalsystem_t *decalsystem = &ent->decalsystem;
10574 if (!decalsystem->numdecals)
10577 if (r_showsurfaces.integer)
10580 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10582 R_DecalSystem_Reset(decalsystem);
10586 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10587 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10589 if (decalsystem->lastupdatetime)
10590 frametime = (cl.time - decalsystem->lastupdatetime);
10593 decalsystem->lastupdatetime = cl.time;
10594 decal = decalsystem->decals;
10595 numdecals = decalsystem->numdecals;
10597 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10599 if (decal->color4f[0][3])
10601 decal->lived += frametime;
10602 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10604 memset(decal, 0, sizeof(*decal));
10605 if (decalsystem->freedecal > i)
10606 decalsystem->freedecal = i;
10610 decal = decalsystem->decals;
10611 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10614 // collapse the array by shuffling the tail decals into the gaps
10617 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10618 decalsystem->freedecal++;
10619 if (decalsystem->freedecal == numdecals)
10621 decal[decalsystem->freedecal] = decal[--numdecals];
10624 decalsystem->numdecals = numdecals;
10626 if (numdecals <= 0)
10628 // if there are no decals left, reset decalsystem
10629 R_DecalSystem_Reset(decalsystem);
10633 extern skinframe_t *decalskinframe;
10634 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10637 decalsystem_t *decalsystem = &ent->decalsystem;
10646 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10649 numdecals = decalsystem->numdecals;
10653 if (r_showsurfaces.integer)
10656 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10658 R_DecalSystem_Reset(decalsystem);
10662 // if the model is static it doesn't matter what value we give for
10663 // wantnormals and wanttangents, so this logic uses only rules applicable
10664 // to a model, knowing that they are meaningless otherwise
10665 if (ent == r_refdef.scene.worldentity)
10666 RSurf_ActiveWorldEntity();
10668 RSurf_ActiveModelEntity(ent, false, false, false);
10670 decalsystem->lastupdatetime = cl.time;
10671 decal = decalsystem->decals;
10673 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10675 // update vertex positions for animated models
10676 v3f = decalsystem->vertex3f;
10677 c4f = decalsystem->color4f;
10678 t2f = decalsystem->texcoord2f;
10679 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10681 if (!decal->color4f[0][3])
10684 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10687 // update color values for fading decals
10688 if (decal->lived >= cl_decals_time.value)
10689 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10693 c4f[ 0] = decal->color4f[0][0] * alpha;
10694 c4f[ 1] = decal->color4f[0][1] * alpha;
10695 c4f[ 2] = decal->color4f[0][2] * alpha;
10697 c4f[ 4] = decal->color4f[1][0] * alpha;
10698 c4f[ 5] = decal->color4f[1][1] * alpha;
10699 c4f[ 6] = decal->color4f[1][2] * alpha;
10701 c4f[ 8] = decal->color4f[2][0] * alpha;
10702 c4f[ 9] = decal->color4f[2][1] * alpha;
10703 c4f[10] = decal->color4f[2][2] * alpha;
10706 t2f[0] = decal->texcoord2f[0][0];
10707 t2f[1] = decal->texcoord2f[0][1];
10708 t2f[2] = decal->texcoord2f[1][0];
10709 t2f[3] = decal->texcoord2f[1][1];
10710 t2f[4] = decal->texcoord2f[2][0];
10711 t2f[5] = decal->texcoord2f[2][1];
10713 // update vertex positions for animated models
10714 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10716 e = rsurface.modelelement3i + 3*decal->triangleindex;
10717 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10718 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10719 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10723 VectorCopy(decal->vertex3f[0], v3f);
10724 VectorCopy(decal->vertex3f[1], v3f + 3);
10725 VectorCopy(decal->vertex3f[2], v3f + 6);
10728 if (r_refdef.fogenabled)
10730 alpha = RSurf_FogVertex(v3f);
10731 VectorScale(c4f, alpha, c4f);
10732 alpha = RSurf_FogVertex(v3f + 3);
10733 VectorScale(c4f + 4, alpha, c4f + 4);
10734 alpha = RSurf_FogVertex(v3f + 6);
10735 VectorScale(c4f + 8, alpha, c4f + 8);
10746 r_refdef.stats.drawndecals += numtris;
10748 // now render the decals all at once
10749 // (this assumes they all use one particle font texture!)
10750 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);
10751 // R_Mesh_ResetTextureState();
10752 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10753 GL_DepthMask(false);
10754 GL_DepthRange(0, 1);
10755 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10756 GL_DepthTest(true);
10757 GL_CullFace(GL_NONE);
10758 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10759 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10760 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10764 static void R_DrawModelDecals(void)
10768 // fade faster when there are too many decals
10769 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10770 for (i = 0;i < r_refdef.scene.numentities;i++)
10771 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10773 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10774 for (i = 0;i < r_refdef.scene.numentities;i++)
10775 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10776 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10778 R_DecalSystem_ApplySplatEntitiesQueue();
10780 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10781 for (i = 0;i < r_refdef.scene.numentities;i++)
10782 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10784 r_refdef.stats.totaldecals += numdecals;
10786 if (r_showsurfaces.integer)
10789 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10791 for (i = 0;i < r_refdef.scene.numentities;i++)
10793 if (!r_refdef.viewcache.entityvisible[i])
10795 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10796 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10800 extern cvar_t mod_collision_bih;
10801 void R_DrawDebugModel(void)
10803 entity_render_t *ent = rsurface.entity;
10804 int i, j, k, l, flagsmask;
10805 const msurface_t *surface;
10806 dp_model_t *model = ent->model;
10809 switch(vid.renderpath)
10811 case RENDERPATH_GL11:
10812 case RENDERPATH_GL13:
10813 case RENDERPATH_GL20:
10815 case RENDERPATH_D3D9:
10816 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10818 case RENDERPATH_D3D10:
10819 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10821 case RENDERPATH_D3D11:
10822 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10824 case RENDERPATH_SOFT:
10825 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10827 case RENDERPATH_GLES2:
10828 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10832 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10834 // R_Mesh_ResetTextureState();
10835 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10836 GL_DepthRange(0, 1);
10837 GL_DepthTest(!r_showdisabledepthtest.integer);
10838 GL_DepthMask(false);
10839 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10841 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10845 qboolean cullbox = ent == r_refdef.scene.worldentity;
10846 const q3mbrush_t *brush;
10847 const bih_t *bih = &model->collision_bih;
10848 const bih_leaf_t *bihleaf;
10849 float vertex3f[3][3];
10850 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10852 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10854 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10856 switch (bihleaf->type)
10859 brush = model->brush.data_brushes + bihleaf->itemindex;
10860 if (brush->colbrushf && brush->colbrushf->numtriangles)
10862 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);
10863 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10864 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10867 case BIH_COLLISIONTRIANGLE:
10868 triangleindex = bihleaf->itemindex;
10869 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10870 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10871 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10872 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);
10873 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10874 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10876 case BIH_RENDERTRIANGLE:
10877 triangleindex = bihleaf->itemindex;
10878 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10879 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10880 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10881 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);
10882 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10883 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10889 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10891 if (r_showtris.integer || (r_shownormals.value != 0))
10893 if (r_showdisabledepthtest.integer)
10895 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10896 GL_DepthMask(false);
10900 GL_BlendFunc(GL_ONE, GL_ZERO);
10901 GL_DepthMask(true);
10903 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10905 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10907 rsurface.texture = R_GetCurrentTexture(surface->texture);
10908 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10910 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10911 if (r_showtris.value > 0)
10913 if (!rsurface.texture->currentlayers->depthmask)
10914 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10915 else if (ent == r_refdef.scene.worldentity)
10916 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10918 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10919 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10920 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10922 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10925 if (r_shownormals.value < 0)
10927 qglBegin(GL_LINES);
10928 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10930 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10931 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10932 qglVertex3f(v[0], v[1], v[2]);
10933 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10934 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10935 qglVertex3f(v[0], v[1], v[2]);
10940 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10942 qglBegin(GL_LINES);
10943 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10945 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10946 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10947 qglVertex3f(v[0], v[1], v[2]);
10948 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10949 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10950 qglVertex3f(v[0], v[1], v[2]);
10954 qglBegin(GL_LINES);
10955 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10957 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10958 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10959 qglVertex3f(v[0], v[1], v[2]);
10960 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10961 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10962 qglVertex3f(v[0], v[1], v[2]);
10966 qglBegin(GL_LINES);
10967 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10969 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10970 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10971 qglVertex3f(v[0], v[1], v[2]);
10972 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10973 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10974 qglVertex3f(v[0], v[1], v[2]);
10981 rsurface.texture = NULL;
10985 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10986 int r_maxsurfacelist = 0;
10987 const msurface_t **r_surfacelist = NULL;
10988 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10990 int i, j, endj, flagsmask;
10991 dp_model_t *model = r_refdef.scene.worldmodel;
10992 msurface_t *surfaces;
10993 unsigned char *update;
10994 int numsurfacelist = 0;
10998 if (r_maxsurfacelist < model->num_surfaces)
11000 r_maxsurfacelist = model->num_surfaces;
11002 Mem_Free((msurface_t**)r_surfacelist);
11003 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11006 RSurf_ActiveWorldEntity();
11008 surfaces = model->data_surfaces;
11009 update = model->brushq1.lightmapupdateflags;
11011 // update light styles on this submodel
11012 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11014 model_brush_lightstyleinfo_t *style;
11015 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11017 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11019 int *list = style->surfacelist;
11020 style->value = r_refdef.scene.lightstylevalue[style->style];
11021 for (j = 0;j < style->numsurfaces;j++)
11022 update[list[j]] = true;
11027 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11031 R_DrawDebugModel();
11032 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11036 rsurface.lightmaptexture = NULL;
11037 rsurface.deluxemaptexture = NULL;
11038 rsurface.uselightmaptexture = false;
11039 rsurface.texture = NULL;
11040 rsurface.rtlight = NULL;
11041 numsurfacelist = 0;
11042 // add visible surfaces to draw list
11043 for (i = 0;i < model->nummodelsurfaces;i++)
11045 j = model->sortedmodelsurfaces[i];
11046 if (r_refdef.viewcache.world_surfacevisible[j])
11047 r_surfacelist[numsurfacelist++] = surfaces + j;
11049 // update lightmaps if needed
11050 if (model->brushq1.firstrender)
11052 model->brushq1.firstrender = false;
11053 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11055 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11059 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11060 if (r_refdef.viewcache.world_surfacevisible[j])
11062 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11064 // don't do anything if there were no surfaces
11065 if (!numsurfacelist)
11067 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11070 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11072 // add to stats if desired
11073 if (r_speeds.integer && !skysurfaces && !depthonly)
11075 r_refdef.stats.world_surfaces += numsurfacelist;
11076 for (j = 0;j < numsurfacelist;j++)
11077 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11080 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11083 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11085 int i, j, endj, flagsmask;
11086 dp_model_t *model = ent->model;
11087 msurface_t *surfaces;
11088 unsigned char *update;
11089 int numsurfacelist = 0;
11093 if (r_maxsurfacelist < model->num_surfaces)
11095 r_maxsurfacelist = model->num_surfaces;
11097 Mem_Free((msurface_t **)r_surfacelist);
11098 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11101 // if the model is static it doesn't matter what value we give for
11102 // wantnormals and wanttangents, so this logic uses only rules applicable
11103 // to a model, knowing that they are meaningless otherwise
11104 if (ent == r_refdef.scene.worldentity)
11105 RSurf_ActiveWorldEntity();
11106 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11107 RSurf_ActiveModelEntity(ent, false, false, false);
11109 RSurf_ActiveModelEntity(ent, true, true, true);
11110 else if (depthonly)
11112 switch (vid.renderpath)
11114 case RENDERPATH_GL20:
11115 case RENDERPATH_D3D9:
11116 case RENDERPATH_D3D10:
11117 case RENDERPATH_D3D11:
11118 case RENDERPATH_SOFT:
11119 case RENDERPATH_GLES2:
11120 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11122 case RENDERPATH_GL13:
11123 case RENDERPATH_GL11:
11124 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11130 switch (vid.renderpath)
11132 case RENDERPATH_GL20:
11133 case RENDERPATH_D3D9:
11134 case RENDERPATH_D3D10:
11135 case RENDERPATH_D3D11:
11136 case RENDERPATH_SOFT:
11137 case RENDERPATH_GLES2:
11138 RSurf_ActiveModelEntity(ent, true, true, false);
11140 case RENDERPATH_GL13:
11141 case RENDERPATH_GL11:
11142 RSurf_ActiveModelEntity(ent, true, false, false);
11147 surfaces = model->data_surfaces;
11148 update = model->brushq1.lightmapupdateflags;
11150 // update light styles
11151 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11153 model_brush_lightstyleinfo_t *style;
11154 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11156 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11158 int *list = style->surfacelist;
11159 style->value = r_refdef.scene.lightstylevalue[style->style];
11160 for (j = 0;j < style->numsurfaces;j++)
11161 update[list[j]] = true;
11166 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11170 R_DrawDebugModel();
11171 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11175 rsurface.lightmaptexture = NULL;
11176 rsurface.deluxemaptexture = NULL;
11177 rsurface.uselightmaptexture = false;
11178 rsurface.texture = NULL;
11179 rsurface.rtlight = NULL;
11180 numsurfacelist = 0;
11181 // add visible surfaces to draw list
11182 for (i = 0;i < model->nummodelsurfaces;i++)
11183 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11184 // don't do anything if there were no surfaces
11185 if (!numsurfacelist)
11187 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11190 // update lightmaps if needed
11194 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11199 R_BuildLightMap(ent, surfaces + j);
11204 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11206 R_BuildLightMap(ent, surfaces + j);
11207 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11209 // add to stats if desired
11210 if (r_speeds.integer && !skysurfaces && !depthonly)
11212 r_refdef.stats.entities_surfaces += numsurfacelist;
11213 for (j = 0;j < numsurfacelist;j++)
11214 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11217 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11220 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11222 static texture_t texture;
11223 static msurface_t surface;
11224 const msurface_t *surfacelist = &surface;
11226 // fake enough texture and surface state to render this geometry
11228 texture.update_lastrenderframe = -1; // regenerate this texture
11229 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11230 texture.currentskinframe = skinframe;
11231 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11232 texture.offsetmapping = OFFSETMAPPING_OFF;
11233 texture.offsetscale = 1;
11234 texture.specularscalemod = 1;
11235 texture.specularpowermod = 1;
11237 surface.texture = &texture;
11238 surface.num_triangles = numtriangles;
11239 surface.num_firsttriangle = firsttriangle;
11240 surface.num_vertices = numvertices;
11241 surface.num_firstvertex = firstvertex;
11244 rsurface.texture = R_GetCurrentTexture(surface.texture);
11245 rsurface.lightmaptexture = NULL;
11246 rsurface.deluxemaptexture = NULL;
11247 rsurface.uselightmaptexture = false;
11248 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11251 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)
11253 static msurface_t surface;
11254 const msurface_t *surfacelist = &surface;
11256 // fake enough texture and surface state to render this geometry
11257 surface.texture = texture;
11258 surface.num_triangles = numtriangles;
11259 surface.num_firsttriangle = firsttriangle;
11260 surface.num_vertices = numvertices;
11261 surface.num_firstvertex = firstvertex;
11264 rsurface.texture = R_GetCurrentTexture(surface.texture);
11265 rsurface.lightmaptexture = NULL;
11266 rsurface.deluxemaptexture = NULL;
11267 rsurface.uselightmaptexture = false;
11268 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);