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_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
211 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)"};
213 extern cvar_t v_glslgamma;
215 extern qboolean v_flipped_state;
217 static struct r_bloomstate_s
222 int bloomwidth, bloomheight;
224 int screentexturewidth, screentextureheight;
225 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
227 int bloomtexturewidth, bloomtextureheight;
228 rtexture_t *texture_bloom;
230 // arrays for rendering the screen passes
231 float screentexcoord2f[8];
232 float bloomtexcoord2f[8];
233 float offsettexcoord2f[8];
235 r_viewport_t viewport;
239 r_waterstate_t r_waterstate;
241 /// shadow volume bsp struct with automatically growing nodes buffer
244 rtexture_t *r_texture_blanknormalmap;
245 rtexture_t *r_texture_white;
246 rtexture_t *r_texture_grey128;
247 rtexture_t *r_texture_black;
248 rtexture_t *r_texture_notexture;
249 rtexture_t *r_texture_whitecube;
250 rtexture_t *r_texture_normalizationcube;
251 rtexture_t *r_texture_fogattenuation;
252 rtexture_t *r_texture_fogheighttexture;
253 rtexture_t *r_texture_gammaramps;
254 unsigned int r_texture_gammaramps_serial;
255 //rtexture_t *r_texture_fogintensity;
256 rtexture_t *r_texture_reflectcube;
258 // TODO: hash lookups?
259 typedef struct cubemapinfo_s
266 int r_texture_numcubemaps;
267 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
269 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
270 unsigned int r_numqueries;
271 unsigned int r_maxqueries;
273 typedef struct r_qwskincache_s
275 char name[MAX_QPATH];
276 skinframe_t *skinframe;
280 static r_qwskincache_t *r_qwskincache;
281 static int r_qwskincache_size;
283 /// vertex coordinates for a quad that covers the screen exactly
284 extern const float r_screenvertex3f[12];
285 extern const float r_d3dscreenvertex3f[12];
286 const float r_screenvertex3f[12] =
293 const float r_d3dscreenvertex3f[12] =
301 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
304 for (i = 0;i < verts;i++)
315 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
318 for (i = 0;i < verts;i++)
328 // FIXME: move this to client?
331 if (gamemode == GAME_NEHAHRA)
333 Cvar_Set("gl_fogenable", "0");
334 Cvar_Set("gl_fogdensity", "0.2");
335 Cvar_Set("gl_fogred", "0.3");
336 Cvar_Set("gl_foggreen", "0.3");
337 Cvar_Set("gl_fogblue", "0.3");
339 r_refdef.fog_density = 0;
340 r_refdef.fog_red = 0;
341 r_refdef.fog_green = 0;
342 r_refdef.fog_blue = 0;
343 r_refdef.fog_alpha = 1;
344 r_refdef.fog_start = 0;
345 r_refdef.fog_end = 16384;
346 r_refdef.fog_height = 1<<30;
347 r_refdef.fog_fadedepth = 128;
348 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
351 static void R_BuildBlankTextures(void)
353 unsigned char data[4];
354 data[2] = 128; // normal X
355 data[1] = 128; // normal Y
356 data[0] = 255; // normal Z
357 data[3] = 128; // height
358 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
373 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376 static void R_BuildNoTexture(void)
379 unsigned char pix[16][16][4];
380 // this makes a light grey/dark grey checkerboard texture
381 for (y = 0;y < 16;y++)
383 for (x = 0;x < 16;x++)
385 if ((y < 8) ^ (x < 8))
401 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
404 static void R_BuildWhiteCube(void)
406 unsigned char data[6*1*1*4];
407 memset(data, 255, sizeof(data));
408 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
411 static void R_BuildNormalizationCube(void)
415 vec_t s, t, intensity;
418 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
419 for (side = 0;side < 6;side++)
421 for (y = 0;y < NORMSIZE;y++)
423 for (x = 0;x < NORMSIZE;x++)
425 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
426 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
461 intensity = 127.0f / sqrt(DotProduct(v, v));
462 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
463 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
464 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
465 data[((side*64+y)*64+x)*4+3] = 255;
469 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
473 static void R_BuildFogTexture(void)
477 unsigned char data1[FOGWIDTH][4];
478 //unsigned char data2[FOGWIDTH][4];
481 r_refdef.fogmasktable_start = r_refdef.fog_start;
482 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
483 r_refdef.fogmasktable_range = r_refdef.fogrange;
484 r_refdef.fogmasktable_density = r_refdef.fog_density;
486 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
487 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
489 d = (x * r - r_refdef.fogmasktable_start);
490 if(developer_extra.integer)
491 Con_DPrintf("%f ", d);
493 if (r_fog_exp2.integer)
494 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
496 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
497 if(developer_extra.integer)
498 Con_DPrintf(" : %f ", alpha);
499 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
500 if(developer_extra.integer)
501 Con_DPrintf(" = %f\n", alpha);
502 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
505 for (x = 0;x < FOGWIDTH;x++)
507 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
512 //data2[x][0] = 255 - b;
513 //data2[x][1] = 255 - b;
514 //data2[x][2] = 255 - b;
517 if (r_texture_fogattenuation)
519 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
524 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
525 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
529 static void R_BuildFogHeightTexture(void)
531 unsigned char *inpixels;
539 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
540 if (r_refdef.fogheighttexturename[0])
541 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
544 r_refdef.fog_height_tablesize = 0;
545 if (r_texture_fogheighttexture)
546 R_FreeTexture(r_texture_fogheighttexture);
547 r_texture_fogheighttexture = NULL;
548 if (r_refdef.fog_height_table2d)
549 Mem_Free(r_refdef.fog_height_table2d);
550 r_refdef.fog_height_table2d = NULL;
551 if (r_refdef.fog_height_table1d)
552 Mem_Free(r_refdef.fog_height_table1d);
553 r_refdef.fog_height_table1d = NULL;
557 r_refdef.fog_height_tablesize = size;
558 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
559 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
560 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
562 // LordHavoc: now the magic - what is that table2d for? it is a cooked
563 // average fog color table accounting for every fog layer between a point
564 // and the camera. (Note: attenuation is handled separately!)
565 for (y = 0;y < size;y++)
567 for (x = 0;x < size;x++)
573 for (j = x;j <= y;j++)
575 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
581 for (j = x;j >= y;j--)
583 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
588 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
589 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
590 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
591 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
594 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
597 //=======================================================================================================================================================
599 static const char *builtinshaderstring =
600 #include "shader_glsl.h"
603 const char *builtinhlslshaderstring =
604 #include "shader_hlsl.h"
607 char *glslshaderstring = NULL;
608 char *hlslshaderstring = NULL;
610 //=======================================================================================================================================================
612 typedef struct shaderpermutationinfo_s
617 shaderpermutationinfo_t;
619 typedef struct shadermodeinfo_s
621 const char *vertexfilename;
622 const char *geometryfilename;
623 const char *fragmentfilename;
629 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
630 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
632 {"#define USEDIFFUSE\n", " diffuse"},
633 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
634 {"#define USEVIEWTINT\n", " viewtint"},
635 {"#define USECOLORMAPPING\n", " colormapping"},
636 {"#define USESATURATION\n", " saturation"},
637 {"#define USEFOGINSIDE\n", " foginside"},
638 {"#define USEFOGOUTSIDE\n", " fogoutside"},
639 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
640 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
641 {"#define USEGAMMARAMPS\n", " gammaramps"},
642 {"#define USECUBEFILTER\n", " cubefilter"},
643 {"#define USEGLOW\n", " glow"},
644 {"#define USEBLOOM\n", " bloom"},
645 {"#define USESPECULAR\n", " specular"},
646 {"#define USEPOSTPROCESSING\n", " postprocessing"},
647 {"#define USEREFLECTION\n", " reflection"},
648 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
649 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
650 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
651 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
652 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
653 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
654 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
655 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
656 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
657 {"#define USEALPHAKILL\n", " alphakill"},
658 {"#define USEREFLECTCUBE\n", " reflectcube"},
659 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
660 {"#define USEBOUNCEGRID\n", " bouncegrid"},
661 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
664 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
665 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
667 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
669 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
685 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
705 struct r_glsl_permutation_s;
706 typedef struct r_glsl_permutation_s
709 struct r_glsl_permutation_s *hashnext;
711 unsigned int permutation;
713 /// indicates if we have tried compiling this permutation already
715 /// 0 if compilation failed
717 // texture units assigned to each detected uniform
718 int tex_Texture_First;
719 int tex_Texture_Second;
720 int tex_Texture_GammaRamps;
721 int tex_Texture_Normal;
722 int tex_Texture_Color;
723 int tex_Texture_Gloss;
724 int tex_Texture_Glow;
725 int tex_Texture_SecondaryNormal;
726 int tex_Texture_SecondaryColor;
727 int tex_Texture_SecondaryGloss;
728 int tex_Texture_SecondaryGlow;
729 int tex_Texture_Pants;
730 int tex_Texture_Shirt;
731 int tex_Texture_FogHeightTexture;
732 int tex_Texture_FogMask;
733 int tex_Texture_Lightmap;
734 int tex_Texture_Deluxemap;
735 int tex_Texture_Attenuation;
736 int tex_Texture_Cube;
737 int tex_Texture_Refraction;
738 int tex_Texture_Reflection;
739 int tex_Texture_ShadowMap2D;
740 int tex_Texture_CubeProjection;
741 int tex_Texture_ScreenDepth;
742 int tex_Texture_ScreenNormalMap;
743 int tex_Texture_ScreenDiffuse;
744 int tex_Texture_ScreenSpecular;
745 int tex_Texture_ReflectMask;
746 int tex_Texture_ReflectCube;
747 int tex_Texture_BounceGrid;
748 /// locations of detected uniforms in program object, or -1 if not found
749 int loc_Texture_First;
750 int loc_Texture_Second;
751 int loc_Texture_GammaRamps;
752 int loc_Texture_Normal;
753 int loc_Texture_Color;
754 int loc_Texture_Gloss;
755 int loc_Texture_Glow;
756 int loc_Texture_SecondaryNormal;
757 int loc_Texture_SecondaryColor;
758 int loc_Texture_SecondaryGloss;
759 int loc_Texture_SecondaryGlow;
760 int loc_Texture_Pants;
761 int loc_Texture_Shirt;
762 int loc_Texture_FogHeightTexture;
763 int loc_Texture_FogMask;
764 int loc_Texture_Lightmap;
765 int loc_Texture_Deluxemap;
766 int loc_Texture_Attenuation;
767 int loc_Texture_Cube;
768 int loc_Texture_Refraction;
769 int loc_Texture_Reflection;
770 int loc_Texture_ShadowMap2D;
771 int loc_Texture_CubeProjection;
772 int loc_Texture_ScreenDepth;
773 int loc_Texture_ScreenNormalMap;
774 int loc_Texture_ScreenDiffuse;
775 int loc_Texture_ScreenSpecular;
776 int loc_Texture_ReflectMask;
777 int loc_Texture_ReflectCube;
778 int loc_Texture_BounceGrid;
780 int loc_BloomBlur_Parameters;
782 int loc_Color_Ambient;
783 int loc_Color_Diffuse;
784 int loc_Color_Specular;
788 int loc_DeferredColor_Ambient;
789 int loc_DeferredColor_Diffuse;
790 int loc_DeferredColor_Specular;
791 int loc_DeferredMod_Diffuse;
792 int loc_DeferredMod_Specular;
793 int loc_DistortScaleRefractReflect;
796 int loc_FogHeightFade;
798 int loc_FogPlaneViewDist;
799 int loc_FogRangeRecip;
802 int loc_LightPosition;
803 int loc_OffsetMapping_ScaleSteps;
805 int loc_ReflectColor;
806 int loc_ReflectFactor;
807 int loc_ReflectOffset;
808 int loc_RefractColor;
810 int loc_ScreenCenterRefractReflect;
811 int loc_ScreenScaleRefractReflect;
812 int loc_ScreenToDepth;
813 int loc_ShadowMap_Parameters;
814 int loc_ShadowMap_TextureScale;
815 int loc_SpecularPower;
820 int loc_ViewTintColor;
822 int loc_ModelToLight;
824 int loc_BackgroundTexMatrix;
825 int loc_ModelViewProjectionMatrix;
826 int loc_ModelViewMatrix;
827 int loc_PixelToScreenTexCoord;
828 int loc_ModelToReflectCube;
829 int loc_ShadowMapMatrix;
830 int loc_BloomColorSubtract;
831 int loc_NormalmapScrollBlend;
832 int loc_BounceGridMatrix;
833 int loc_BounceGridIntensity;
835 r_glsl_permutation_t;
837 #define SHADERPERMUTATION_HASHSIZE 256
840 // non-degradable "lightweight" shader parameters to keep the permutations simpler
841 // these can NOT degrade! only use for simple stuff
844 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
845 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
846 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
847 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
848 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
849 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
850 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
852 #define SHADERSTATICPARMS_COUNT 7
854 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
855 static int shaderstaticparms_count = 0;
857 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
858 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
859 qboolean R_CompileShader_CheckStaticParms(void)
861 static int r_compileshader_staticparms_save[1];
862 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
863 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
866 if (r_glsl_saturation_redcompensate.integer)
867 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
868 if (r_glsl_vertextextureblend_usebothalphas.integer)
869 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
870 if (r_shadow_glossexact.integer)
871 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
872 if (r_glsl_postprocess.integer)
874 if (r_glsl_postprocess_uservec1_enable.integer)
875 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
876 if (r_glsl_postprocess_uservec2_enable.integer)
877 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
878 if (r_glsl_postprocess_uservec3_enable.integer)
879 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
880 if (r_glsl_postprocess_uservec4_enable.integer)
881 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
883 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
886 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
887 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
888 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
890 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
891 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
893 shaderstaticparms_count = 0;
896 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
897 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
898 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
899 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
900 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
901 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
902 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
905 /// information about each possible shader permutation
906 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
907 /// currently selected permutation
908 r_glsl_permutation_t *r_glsl_permutation;
909 /// storage for permutations linked in the hash table
910 memexpandablearray_t r_glsl_permutationarray;
912 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
914 //unsigned int hashdepth = 0;
915 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
916 r_glsl_permutation_t *p;
917 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
919 if (p->mode == mode && p->permutation == permutation)
921 //if (hashdepth > 10)
922 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
927 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
929 p->permutation = permutation;
930 p->hashnext = r_glsl_permutationhash[mode][hashindex];
931 r_glsl_permutationhash[mode][hashindex] = p;
932 //if (hashdepth > 10)
933 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
937 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
940 if (!filename || !filename[0])
942 if (!strcmp(filename, "glsl/default.glsl"))
944 if (!glslshaderstring)
946 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
947 if (glslshaderstring)
948 Con_DPrintf("Loading shaders from file %s...\n", filename);
950 glslshaderstring = (char *)builtinshaderstring;
952 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
953 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
956 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
959 if (printfromdisknotice)
960 Con_DPrintf("from disk %s... ", filename);
966 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
970 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
971 char *vertexstring, *geometrystring, *fragmentstring;
972 char permutationname[256];
973 int vertstrings_count = 0;
974 int geomstrings_count = 0;
975 int fragstrings_count = 0;
976 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
977 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
978 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
985 permutationname[0] = 0;
986 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
987 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
988 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
990 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
992 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
993 if(vid.support.gl20shaders130)
995 vertstrings_list[vertstrings_count++] = "#version 130\n";
996 geomstrings_list[geomstrings_count++] = "#version 130\n";
997 fragstrings_list[fragstrings_count++] = "#version 130\n";
998 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
999 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1000 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1003 // the first pretext is which type of shader to compile as
1004 // (later these will all be bound together as a program object)
1005 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1006 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1007 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1009 // the second pretext is the mode (for example a light source)
1010 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1011 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1012 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1013 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1015 // now add all the permutation pretexts
1016 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1018 if (permutation & (1<<i))
1020 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1021 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1022 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1023 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1027 // keep line numbers correct
1028 vertstrings_list[vertstrings_count++] = "\n";
1029 geomstrings_list[geomstrings_count++] = "\n";
1030 fragstrings_list[fragstrings_count++] = "\n";
1035 R_CompileShader_AddStaticParms(mode, permutation);
1036 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1037 vertstrings_count += shaderstaticparms_count;
1038 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1039 geomstrings_count += shaderstaticparms_count;
1040 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1041 fragstrings_count += shaderstaticparms_count;
1043 // now append the shader text itself
1044 vertstrings_list[vertstrings_count++] = vertexstring;
1045 geomstrings_list[geomstrings_count++] = geometrystring;
1046 fragstrings_list[fragstrings_count++] = fragmentstring;
1048 // if any sources were NULL, clear the respective list
1050 vertstrings_count = 0;
1051 if (!geometrystring)
1052 geomstrings_count = 0;
1053 if (!fragmentstring)
1054 fragstrings_count = 0;
1056 // compile the shader program
1057 if (vertstrings_count + geomstrings_count + fragstrings_count)
1058 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1062 qglUseProgram(p->program);CHECKGLERROR
1063 // look up all the uniform variable names we care about, so we don't
1064 // have to look them up every time we set them
1066 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1067 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1068 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1069 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1070 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1071 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1072 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1073 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1074 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1075 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1076 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1077 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1078 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1079 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1080 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1081 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1082 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1083 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1084 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1085 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1086 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1087 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1088 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1089 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1090 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1091 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1092 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1093 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1094 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1095 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1096 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1097 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1098 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1099 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1100 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1101 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1102 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1103 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1104 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1105 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1106 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1107 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1108 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1109 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1110 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1111 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1112 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1113 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1114 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1115 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1116 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1117 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1118 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1119 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1120 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1121 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1122 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1123 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1124 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1125 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1126 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1127 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1128 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1129 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1130 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1131 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1132 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1133 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1134 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1135 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1136 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1137 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1138 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1139 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1140 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1141 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1142 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1143 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1144 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1145 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1146 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1147 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1148 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1149 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1150 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1151 // initialize the samplers to refer to the texture units we use
1152 p->tex_Texture_First = -1;
1153 p->tex_Texture_Second = -1;
1154 p->tex_Texture_GammaRamps = -1;
1155 p->tex_Texture_Normal = -1;
1156 p->tex_Texture_Color = -1;
1157 p->tex_Texture_Gloss = -1;
1158 p->tex_Texture_Glow = -1;
1159 p->tex_Texture_SecondaryNormal = -1;
1160 p->tex_Texture_SecondaryColor = -1;
1161 p->tex_Texture_SecondaryGloss = -1;
1162 p->tex_Texture_SecondaryGlow = -1;
1163 p->tex_Texture_Pants = -1;
1164 p->tex_Texture_Shirt = -1;
1165 p->tex_Texture_FogHeightTexture = -1;
1166 p->tex_Texture_FogMask = -1;
1167 p->tex_Texture_Lightmap = -1;
1168 p->tex_Texture_Deluxemap = -1;
1169 p->tex_Texture_Attenuation = -1;
1170 p->tex_Texture_Cube = -1;
1171 p->tex_Texture_Refraction = -1;
1172 p->tex_Texture_Reflection = -1;
1173 p->tex_Texture_ShadowMap2D = -1;
1174 p->tex_Texture_CubeProjection = -1;
1175 p->tex_Texture_ScreenDepth = -1;
1176 p->tex_Texture_ScreenNormalMap = -1;
1177 p->tex_Texture_ScreenDiffuse = -1;
1178 p->tex_Texture_ScreenSpecular = -1;
1179 p->tex_Texture_ReflectMask = -1;
1180 p->tex_Texture_ReflectCube = -1;
1181 p->tex_Texture_BounceGrid = -1;
1183 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1184 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1185 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1186 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1187 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1188 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1189 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1190 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1191 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1192 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1193 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1194 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1195 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1196 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1197 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1198 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1199 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1200 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1201 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1202 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1203 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1204 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1205 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1206 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1207 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1208 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1209 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1210 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1211 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1212 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1214 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1217 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1221 Mem_Free(vertexstring);
1223 Mem_Free(geometrystring);
1225 Mem_Free(fragmentstring);
1228 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1230 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1231 if (r_glsl_permutation != perm)
1233 r_glsl_permutation = perm;
1234 if (!r_glsl_permutation->program)
1236 if (!r_glsl_permutation->compiled)
1237 R_GLSL_CompilePermutation(perm, mode, permutation);
1238 if (!r_glsl_permutation->program)
1240 // remove features until we find a valid permutation
1242 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1244 // reduce i more quickly whenever it would not remove any bits
1245 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1246 if (!(permutation & j))
1249 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1250 if (!r_glsl_permutation->compiled)
1251 R_GLSL_CompilePermutation(perm, mode, permutation);
1252 if (r_glsl_permutation->program)
1255 if (i >= SHADERPERMUTATION_COUNT)
1257 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1258 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1259 qglUseProgram(0);CHECKGLERROR
1260 return; // no bit left to clear, entire mode is broken
1265 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1267 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1268 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1269 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1276 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1277 extern D3DCAPS9 vid_d3d9caps;
1280 struct r_hlsl_permutation_s;
1281 typedef struct r_hlsl_permutation_s
1283 /// hash lookup data
1284 struct r_hlsl_permutation_s *hashnext;
1286 unsigned int permutation;
1288 /// indicates if we have tried compiling this permutation already
1290 /// NULL if compilation failed
1291 IDirect3DVertexShader9 *vertexshader;
1292 IDirect3DPixelShader9 *pixelshader;
1294 r_hlsl_permutation_t;
1296 typedef enum D3DVSREGISTER_e
1298 D3DVSREGISTER_TexMatrix = 0, // float4x4
1299 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1300 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1301 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1302 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1303 D3DVSREGISTER_ModelToLight = 20, // float4x4
1304 D3DVSREGISTER_EyePosition = 24,
1305 D3DVSREGISTER_FogPlane = 25,
1306 D3DVSREGISTER_LightDir = 26,
1307 D3DVSREGISTER_LightPosition = 27,
1311 typedef enum D3DPSREGISTER_e
1313 D3DPSREGISTER_Alpha = 0,
1314 D3DPSREGISTER_BloomBlur_Parameters = 1,
1315 D3DPSREGISTER_ClientTime = 2,
1316 D3DPSREGISTER_Color_Ambient = 3,
1317 D3DPSREGISTER_Color_Diffuse = 4,
1318 D3DPSREGISTER_Color_Specular = 5,
1319 D3DPSREGISTER_Color_Glow = 6,
1320 D3DPSREGISTER_Color_Pants = 7,
1321 D3DPSREGISTER_Color_Shirt = 8,
1322 D3DPSREGISTER_DeferredColor_Ambient = 9,
1323 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1324 D3DPSREGISTER_DeferredColor_Specular = 11,
1325 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1326 D3DPSREGISTER_DeferredMod_Specular = 13,
1327 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1328 D3DPSREGISTER_EyePosition = 15, // unused
1329 D3DPSREGISTER_FogColor = 16,
1330 D3DPSREGISTER_FogHeightFade = 17,
1331 D3DPSREGISTER_FogPlane = 18,
1332 D3DPSREGISTER_FogPlaneViewDist = 19,
1333 D3DPSREGISTER_FogRangeRecip = 20,
1334 D3DPSREGISTER_LightColor = 21,
1335 D3DPSREGISTER_LightDir = 22, // unused
1336 D3DPSREGISTER_LightPosition = 23,
1337 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1338 D3DPSREGISTER_PixelSize = 25,
1339 D3DPSREGISTER_ReflectColor = 26,
1340 D3DPSREGISTER_ReflectFactor = 27,
1341 D3DPSREGISTER_ReflectOffset = 28,
1342 D3DPSREGISTER_RefractColor = 29,
1343 D3DPSREGISTER_Saturation = 30,
1344 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1345 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1346 D3DPSREGISTER_ScreenToDepth = 33,
1347 D3DPSREGISTER_ShadowMap_Parameters = 34,
1348 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1349 D3DPSREGISTER_SpecularPower = 36,
1350 D3DPSREGISTER_UserVec1 = 37,
1351 D3DPSREGISTER_UserVec2 = 38,
1352 D3DPSREGISTER_UserVec3 = 39,
1353 D3DPSREGISTER_UserVec4 = 40,
1354 D3DPSREGISTER_ViewTintColor = 41,
1355 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1356 D3DPSREGISTER_BloomColorSubtract = 43,
1357 D3DPSREGISTER_ViewToLight = 44, // float4x4
1358 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1359 D3DPSREGISTER_NormalmapScrollBlend = 52,
1364 /// information about each possible shader permutation
1365 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1366 /// currently selected permutation
1367 r_hlsl_permutation_t *r_hlsl_permutation;
1368 /// storage for permutations linked in the hash table
1369 memexpandablearray_t r_hlsl_permutationarray;
1371 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1373 //unsigned int hashdepth = 0;
1374 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1375 r_hlsl_permutation_t *p;
1376 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1378 if (p->mode == mode && p->permutation == permutation)
1380 //if (hashdepth > 10)
1381 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1386 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1388 p->permutation = permutation;
1389 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1390 r_hlsl_permutationhash[mode][hashindex] = p;
1391 //if (hashdepth > 10)
1392 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1396 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1399 if (!filename || !filename[0])
1401 if (!strcmp(filename, "hlsl/default.hlsl"))
1403 if (!hlslshaderstring)
1405 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1406 if (hlslshaderstring)
1407 Con_DPrintf("Loading shaders from file %s...\n", filename);
1409 hlslshaderstring = (char *)builtinhlslshaderstring;
1411 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1412 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1413 return shaderstring;
1415 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1418 if (printfromdisknotice)
1419 Con_DPrintf("from disk %s... ", filename);
1420 return shaderstring;
1422 return shaderstring;
1426 //#include <d3dx9shader.h>
1427 //#include <d3dx9mesh.h>
1429 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1431 DWORD *vsbin = NULL;
1432 DWORD *psbin = NULL;
1433 fs_offset_t vsbinsize;
1434 fs_offset_t psbinsize;
1435 // IDirect3DVertexShader9 *vs = NULL;
1436 // IDirect3DPixelShader9 *ps = NULL;
1437 ID3DXBuffer *vslog = NULL;
1438 ID3DXBuffer *vsbuffer = NULL;
1439 ID3DXConstantTable *vsconstanttable = NULL;
1440 ID3DXBuffer *pslog = NULL;
1441 ID3DXBuffer *psbuffer = NULL;
1442 ID3DXConstantTable *psconstanttable = NULL;
1445 char temp[MAX_INPUTLINE];
1446 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1447 qboolean debugshader = gl_paranoid.integer != 0;
1448 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1449 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1452 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1453 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1455 if ((!vsbin && vertstring) || (!psbin && fragstring))
1457 const char* dllnames_d3dx9 [] =
1481 dllhandle_t d3dx9_dll = NULL;
1482 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1483 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1484 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1485 dllfunction_t d3dx9_dllfuncs[] =
1487 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1488 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1489 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1492 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1494 DWORD shaderflags = 0;
1496 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1497 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1498 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1499 if (vertstring && vertstring[0])
1503 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1504 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1505 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1506 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1509 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1512 vsbinsize = vsbuffer->GetBufferSize();
1513 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1514 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1515 vsbuffer->Release();
1519 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1520 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1524 if (fragstring && fragstring[0])
1528 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1529 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1530 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1531 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1534 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1537 psbinsize = psbuffer->GetBufferSize();
1538 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1539 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1540 psbuffer->Release();
1544 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1545 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1549 Sys_UnloadLibrary(&d3dx9_dll);
1552 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1556 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1557 if (FAILED(vsresult))
1558 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1559 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1560 if (FAILED(psresult))
1561 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1563 // free the shader data
1564 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1565 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1568 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1571 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1572 int vertstring_length = 0;
1573 int geomstring_length = 0;
1574 int fragstring_length = 0;
1576 char *vertexstring, *geometrystring, *fragmentstring;
1577 char *vertstring, *geomstring, *fragstring;
1578 char permutationname[256];
1579 char cachename[256];
1580 int vertstrings_count = 0;
1581 int geomstrings_count = 0;
1582 int fragstrings_count = 0;
1583 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1584 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1585 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1590 p->vertexshader = NULL;
1591 p->pixelshader = NULL;
1593 permutationname[0] = 0;
1595 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1596 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1597 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1599 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1600 strlcat(cachename, "hlsl/", sizeof(cachename));
1602 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1603 vertstrings_count = 0;
1604 geomstrings_count = 0;
1605 fragstrings_count = 0;
1606 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1607 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1608 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1610 // the first pretext is which type of shader to compile as
1611 // (later these will all be bound together as a program object)
1612 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1613 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1614 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1616 // the second pretext is the mode (for example a light source)
1617 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1618 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1619 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1620 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1621 strlcat(cachename, modeinfo->name, sizeof(cachename));
1623 // now add all the permutation pretexts
1624 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1626 if (permutation & (1<<i))
1628 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1629 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1630 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1631 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1632 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1636 // keep line numbers correct
1637 vertstrings_list[vertstrings_count++] = "\n";
1638 geomstrings_list[geomstrings_count++] = "\n";
1639 fragstrings_list[fragstrings_count++] = "\n";
1644 R_CompileShader_AddStaticParms(mode, permutation);
1645 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1646 vertstrings_count += shaderstaticparms_count;
1647 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1648 geomstrings_count += shaderstaticparms_count;
1649 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1650 fragstrings_count += shaderstaticparms_count;
1652 // replace spaces in the cachename with _ characters
1653 for (i = 0;cachename[i];i++)
1654 if (cachename[i] == ' ')
1657 // now append the shader text itself
1658 vertstrings_list[vertstrings_count++] = vertexstring;
1659 geomstrings_list[geomstrings_count++] = geometrystring;
1660 fragstrings_list[fragstrings_count++] = fragmentstring;
1662 // if any sources were NULL, clear the respective list
1664 vertstrings_count = 0;
1665 if (!geometrystring)
1666 geomstrings_count = 0;
1667 if (!fragmentstring)
1668 fragstrings_count = 0;
1670 vertstring_length = 0;
1671 for (i = 0;i < vertstrings_count;i++)
1672 vertstring_length += strlen(vertstrings_list[i]);
1673 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1674 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1675 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1677 geomstring_length = 0;
1678 for (i = 0;i < geomstrings_count;i++)
1679 geomstring_length += strlen(geomstrings_list[i]);
1680 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1681 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1682 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1684 fragstring_length = 0;
1685 for (i = 0;i < fragstrings_count;i++)
1686 fragstring_length += strlen(fragstrings_list[i]);
1687 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1688 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1689 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1691 // try to load the cached shader, or generate one
1692 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1694 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1695 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1697 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1701 Mem_Free(vertstring);
1703 Mem_Free(geomstring);
1705 Mem_Free(fragstring);
1707 Mem_Free(vertexstring);
1709 Mem_Free(geometrystring);
1711 Mem_Free(fragmentstring);
1714 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1715 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1716 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);}
1717 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);}
1718 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);}
1719 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);}
1721 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1722 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1723 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);}
1724 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);}
1725 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);}
1726 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);}
1728 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1730 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1731 if (r_hlsl_permutation != perm)
1733 r_hlsl_permutation = perm;
1734 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1736 if (!r_hlsl_permutation->compiled)
1737 R_HLSL_CompilePermutation(perm, mode, permutation);
1738 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1740 // remove features until we find a valid permutation
1742 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1744 // reduce i more quickly whenever it would not remove any bits
1745 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1746 if (!(permutation & j))
1749 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1750 if (!r_hlsl_permutation->compiled)
1751 R_HLSL_CompilePermutation(perm, mode, permutation);
1752 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1755 if (i >= SHADERPERMUTATION_COUNT)
1757 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1758 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1759 return; // no bit left to clear, entire mode is broken
1763 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1764 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1766 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1767 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1768 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1772 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1774 DPSOFTRAST_SetShader(mode, permutation);
1775 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1776 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1777 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1780 void R_GLSL_Restart_f(void)
1782 unsigned int i, limit;
1783 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1784 Mem_Free(glslshaderstring);
1785 glslshaderstring = NULL;
1786 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1787 Mem_Free(hlslshaderstring);
1788 hlslshaderstring = NULL;
1789 switch(vid.renderpath)
1791 case RENDERPATH_D3D9:
1794 r_hlsl_permutation_t *p;
1795 r_hlsl_permutation = NULL;
1796 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1797 for (i = 0;i < limit;i++)
1799 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1801 if (p->vertexshader)
1802 IDirect3DVertexShader9_Release(p->vertexshader);
1804 IDirect3DPixelShader9_Release(p->pixelshader);
1805 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1808 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1812 case RENDERPATH_D3D10:
1813 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1815 case RENDERPATH_D3D11:
1816 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1818 case RENDERPATH_GL20:
1819 case RENDERPATH_GLES2:
1821 r_glsl_permutation_t *p;
1822 r_glsl_permutation = NULL;
1823 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1824 for (i = 0;i < limit;i++)
1826 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1828 GL_Backend_FreeProgram(p->program);
1829 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1832 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1835 case RENDERPATH_GL13:
1836 case RENDERPATH_GL11:
1838 case RENDERPATH_SOFT:
1843 void R_GLSL_DumpShader_f(void)
1848 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1851 FS_Print(file, "/* The engine may define the following macros:\n");
1852 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1853 for (i = 0;i < SHADERMODE_COUNT;i++)
1854 FS_Print(file, glslshadermodeinfo[i].pretext);
1855 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1856 FS_Print(file, shaderpermutationinfo[i].pretext);
1857 FS_Print(file, "*/\n");
1858 FS_Print(file, builtinshaderstring);
1860 Con_Printf("glsl/default.glsl written\n");
1863 Con_Printf("failed to write to glsl/default.glsl\n");
1865 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1868 FS_Print(file, "/* The engine may define the following macros:\n");
1869 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1870 for (i = 0;i < SHADERMODE_COUNT;i++)
1871 FS_Print(file, hlslshadermodeinfo[i].pretext);
1872 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1873 FS_Print(file, shaderpermutationinfo[i].pretext);
1874 FS_Print(file, "*/\n");
1875 FS_Print(file, builtinhlslshaderstring);
1877 Con_Printf("hlsl/default.hlsl written\n");
1880 Con_Printf("failed to write to hlsl/default.hlsl\n");
1883 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1886 texturemode = GL_MODULATE;
1887 switch (vid.renderpath)
1889 case RENDERPATH_D3D9:
1891 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))));
1892 R_Mesh_TexBind(GL20TU_FIRST , first );
1893 R_Mesh_TexBind(GL20TU_SECOND, second);
1896 case RENDERPATH_D3D10:
1897 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1899 case RENDERPATH_D3D11:
1900 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1902 case RENDERPATH_GL20:
1903 case RENDERPATH_GLES2:
1904 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))));
1905 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1906 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1908 case RENDERPATH_GL13:
1909 R_Mesh_TexBind(0, first );
1910 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1911 R_Mesh_TexBind(1, second);
1913 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1915 case RENDERPATH_GL11:
1916 R_Mesh_TexBind(0, first );
1918 case RENDERPATH_SOFT:
1919 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))));
1920 R_Mesh_TexBind(GL20TU_FIRST , first );
1921 R_Mesh_TexBind(GL20TU_SECOND, second);
1926 void R_SetupShader_DepthOrShadow(void)
1928 switch (vid.renderpath)
1930 case RENDERPATH_D3D9:
1932 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1935 case RENDERPATH_D3D10:
1936 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1938 case RENDERPATH_D3D11:
1939 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1941 case RENDERPATH_GL20:
1942 case RENDERPATH_GLES2:
1943 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1945 case RENDERPATH_GL13:
1946 R_Mesh_TexBind(0, 0);
1947 R_Mesh_TexBind(1, 0);
1949 case RENDERPATH_GL11:
1950 R_Mesh_TexBind(0, 0);
1952 case RENDERPATH_SOFT:
1953 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1958 void R_SetupShader_ShowDepth(void)
1960 switch (vid.renderpath)
1962 case RENDERPATH_D3D9:
1964 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1967 case RENDERPATH_D3D10:
1968 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1970 case RENDERPATH_D3D11:
1971 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973 case RENDERPATH_GL20:
1974 case RENDERPATH_GLES2:
1975 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1977 case RENDERPATH_GL13:
1979 case RENDERPATH_GL11:
1981 case RENDERPATH_SOFT:
1982 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1987 extern qboolean r_shadow_usingdeferredprepass;
1988 extern cvar_t r_shadow_deferred_8bitrange;
1989 extern rtexture_t *r_shadow_attenuationgradienttexture;
1990 extern rtexture_t *r_shadow_attenuation2dtexture;
1991 extern rtexture_t *r_shadow_attenuation3dtexture;
1992 extern qboolean r_shadow_usingshadowmap2d;
1993 extern qboolean r_shadow_usingshadowmaportho;
1994 extern float r_shadow_shadowmap_texturescale[2];
1995 extern float r_shadow_shadowmap_parameters[4];
1996 extern qboolean r_shadow_shadowmapvsdct;
1997 extern qboolean r_shadow_shadowmapsampler;
1998 extern int r_shadow_shadowmappcf;
1999 extern rtexture_t *r_shadow_shadowmap2dtexture;
2000 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2001 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2002 extern matrix4x4_t r_shadow_shadowmapmatrix;
2003 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2004 extern int r_shadow_prepass_width;
2005 extern int r_shadow_prepass_height;
2006 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2007 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2008 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2009 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2010 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2012 #define BLENDFUNC_ALLOWS_COLORMOD 1
2013 #define BLENDFUNC_ALLOWS_FOG 2
2014 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2015 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2016 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2017 static int R_BlendFuncFlags(int src, int dst)
2021 // a blendfunc allows colormod if:
2022 // a) it can never keep the destination pixel invariant, or
2023 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2024 // this is to prevent unintended side effects from colormod
2026 // a blendfunc allows fog if:
2027 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2028 // this is to prevent unintended side effects from fog
2030 // these checks are the output of fogeval.pl
2032 r |= BLENDFUNC_ALLOWS_COLORMOD;
2033 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2034 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2035 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2036 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2037 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2038 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2041 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2042 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2043 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2044 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2045 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2046 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2047 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2048 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2051 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2052 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2053 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058 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)
2060 // select a permutation of the lighting shader appropriate to this
2061 // combination of texture, entity, light source, and fogging, only use the
2062 // minimum features necessary to avoid wasting rendering time in the
2063 // fragment shader on features that are not being used
2064 unsigned int permutation = 0;
2065 unsigned int mode = 0;
2067 static float dummy_colormod[3] = {1, 1, 1};
2068 float *colormod = rsurface.colormod;
2070 matrix4x4_t tempmatrix;
2071 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2072 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2073 permutation |= SHADERPERMUTATION_ALPHAKILL;
2074 if (rsurfacepass == RSURFPASS_BACKGROUND)
2076 // distorted background
2077 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2079 mode = SHADERMODE_WATER;
2080 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2081 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2082 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2084 // this is the right thing to do for wateralpha
2085 GL_BlendFunc(GL_ONE, GL_ZERO);
2086 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2090 // this is the right thing to do for entity alpha
2091 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2092 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2095 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2097 mode = SHADERMODE_REFRACTION;
2098 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2099 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2103 mode = SHADERMODE_GENERIC;
2104 permutation |= SHADERPERMUTATION_DIFFUSE;
2105 GL_BlendFunc(GL_ONE, GL_ZERO);
2106 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2109 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2111 if (r_glsl_offsetmapping.integer)
2113 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2114 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2115 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2116 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2117 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2119 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2120 if (r_glsl_offsetmapping_reliefmapping.integer)
2121 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2124 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2125 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2126 // normalmap (deferred prepass), may use alpha test on diffuse
2127 mode = SHADERMODE_DEFERREDGEOMETRY;
2128 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2129 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2130 GL_BlendFunc(GL_ONE, GL_ZERO);
2131 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2133 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2135 if (r_glsl_offsetmapping.integer)
2137 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2138 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2139 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2140 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2141 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2143 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2144 if (r_glsl_offsetmapping_reliefmapping.integer)
2145 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2148 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2149 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2151 mode = SHADERMODE_LIGHTSOURCE;
2152 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2153 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2154 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2155 permutation |= SHADERPERMUTATION_CUBEFILTER;
2156 if (diffusescale > 0)
2157 permutation |= SHADERPERMUTATION_DIFFUSE;
2158 if (specularscale > 0)
2159 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2160 if (r_refdef.fogenabled)
2161 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2162 if (rsurface.texture->colormapping)
2163 permutation |= SHADERPERMUTATION_COLORMAPPING;
2164 if (r_shadow_usingshadowmap2d)
2166 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2167 if(r_shadow_shadowmapvsdct)
2168 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2170 if (r_shadow_shadowmapsampler)
2171 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2172 if (r_shadow_shadowmappcf > 1)
2173 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2174 else if (r_shadow_shadowmappcf)
2175 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2177 if (rsurface.texture->reflectmasktexture)
2178 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2179 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2180 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2182 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2184 if (r_glsl_offsetmapping.integer)
2186 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2187 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2188 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2189 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2190 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2192 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2193 if (r_glsl_offsetmapping_reliefmapping.integer)
2194 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2197 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2198 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2199 // unshaded geometry (fullbright or ambient model lighting)
2200 mode = SHADERMODE_FLATCOLOR;
2201 ambientscale = diffusescale = specularscale = 0;
2202 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2203 permutation |= SHADERPERMUTATION_GLOW;
2204 if (r_refdef.fogenabled)
2205 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2206 if (rsurface.texture->colormapping)
2207 permutation |= SHADERPERMUTATION_COLORMAPPING;
2208 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2210 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2211 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2213 if (r_shadow_shadowmapsampler)
2214 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2215 if (r_shadow_shadowmappcf > 1)
2216 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2217 else if (r_shadow_shadowmappcf)
2218 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2221 permutation |= SHADERPERMUTATION_REFLECTION;
2222 if (rsurface.texture->reflectmasktexture)
2223 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2224 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2225 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2227 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2229 if (r_glsl_offsetmapping.integer)
2231 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2232 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2233 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2234 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2235 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2237 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2238 if (r_glsl_offsetmapping_reliefmapping.integer)
2239 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2242 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2243 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2244 // directional model lighting
2245 mode = SHADERMODE_LIGHTDIRECTION;
2246 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2247 permutation |= SHADERPERMUTATION_GLOW;
2248 permutation |= SHADERPERMUTATION_DIFFUSE;
2249 if (specularscale > 0)
2250 permutation |= SHADERPERMUTATION_SPECULAR;
2251 if (r_refdef.fogenabled)
2252 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2253 if (rsurface.texture->colormapping)
2254 permutation |= SHADERPERMUTATION_COLORMAPPING;
2255 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2257 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2258 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2260 if (r_shadow_shadowmapsampler)
2261 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2262 if (r_shadow_shadowmappcf > 1)
2263 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2264 else if (r_shadow_shadowmappcf)
2265 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2267 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2268 permutation |= SHADERPERMUTATION_REFLECTION;
2269 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2270 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2271 if (rsurface.texture->reflectmasktexture)
2272 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2273 if (r_shadow_bouncegridtexture)
2275 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2276 if (r_shadow_bouncegriddirectional)
2277 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2279 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2282 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2284 if (r_glsl_offsetmapping.integer)
2286 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2287 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2288 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2289 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2290 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2292 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2293 if (r_glsl_offsetmapping_reliefmapping.integer)
2294 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2297 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2298 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2299 // ambient model lighting
2300 mode = SHADERMODE_LIGHTDIRECTION;
2301 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2302 permutation |= SHADERPERMUTATION_GLOW;
2303 if (r_refdef.fogenabled)
2304 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2305 if (rsurface.texture->colormapping)
2306 permutation |= SHADERPERMUTATION_COLORMAPPING;
2307 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2309 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2310 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312 if (r_shadow_shadowmapsampler)
2313 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2314 if (r_shadow_shadowmappcf > 1)
2315 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2316 else if (r_shadow_shadowmappcf)
2317 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2319 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2320 permutation |= SHADERPERMUTATION_REFLECTION;
2321 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2322 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2323 if (rsurface.texture->reflectmasktexture)
2324 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2325 if (r_shadow_bouncegridtexture)
2327 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2328 if (r_shadow_bouncegriddirectional)
2329 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2331 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2332 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336 if (r_glsl_offsetmapping.integer)
2338 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2339 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2340 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2341 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2342 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2344 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2345 if (r_glsl_offsetmapping_reliefmapping.integer)
2346 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2349 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2350 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2352 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2353 permutation |= SHADERPERMUTATION_GLOW;
2354 if (r_refdef.fogenabled)
2355 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2356 if (rsurface.texture->colormapping)
2357 permutation |= SHADERPERMUTATION_COLORMAPPING;
2358 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2360 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2361 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2363 if (r_shadow_shadowmapsampler)
2364 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2365 if (r_shadow_shadowmappcf > 1)
2366 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2367 else if (r_shadow_shadowmappcf)
2368 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2370 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2371 permutation |= SHADERPERMUTATION_REFLECTION;
2372 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2373 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2374 if (rsurface.texture->reflectmasktexture)
2375 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2376 if (FAKELIGHT_ENABLED)
2378 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2379 mode = SHADERMODE_FAKELIGHT;
2380 permutation |= SHADERPERMUTATION_DIFFUSE;
2381 if (specularscale > 0)
2382 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2384 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2386 // deluxemapping (light direction texture)
2387 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2388 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2390 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2391 permutation |= SHADERPERMUTATION_DIFFUSE;
2392 if (specularscale > 0)
2393 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2397 // fake deluxemapping (uniform light direction in tangentspace)
2398 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2399 permutation |= SHADERPERMUTATION_DIFFUSE;
2400 if (specularscale > 0)
2401 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2403 else if (rsurface.uselightmaptexture)
2405 // ordinary lightmapping (q1bsp, q3bsp)
2406 mode = SHADERMODE_LIGHTMAP;
2410 // ordinary vertex coloring (q3bsp)
2411 mode = SHADERMODE_VERTEXCOLOR;
2413 if (r_shadow_bouncegridtexture)
2415 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2416 if (r_shadow_bouncegriddirectional)
2417 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2423 colormod = dummy_colormod;
2424 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2425 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2426 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2427 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2428 switch(vid.renderpath)
2430 case RENDERPATH_D3D9:
2432 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);
2433 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2434 R_SetupShader_SetPermutationHLSL(mode, permutation);
2435 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2436 if (mode == SHADERMODE_LIGHTSOURCE)
2438 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2439 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2443 if (mode == SHADERMODE_LIGHTDIRECTION)
2445 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2448 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2449 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2450 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2451 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2452 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2454 if (mode == SHADERMODE_LIGHTSOURCE)
2456 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2458 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2459 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2460 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2462 // additive passes are only darkened by fog, not tinted
2463 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2464 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2468 if (mode == SHADERMODE_FLATCOLOR)
2470 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2472 else if (mode == SHADERMODE_LIGHTDIRECTION)
2474 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]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2476 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);
2477 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);
2478 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2479 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2480 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2484 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2486 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);
2487 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);
2488 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490 // additive passes are only darkened by fog, not tinted
2491 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2492 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2494 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2495 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);
2496 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2497 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2501 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2502 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2503 if (mode == SHADERMODE_WATER)
2504 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2506 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2507 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2508 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2509 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));
2510 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2511 if (rsurface.texture->pantstexture)
2512 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2514 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2515 if (rsurface.texture->shirttexture)
2516 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2518 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2519 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2520 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2521 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2522 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2523 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));
2524 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2525 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2527 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2528 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2529 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2530 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2531 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2532 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2533 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2534 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2535 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2536 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2537 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2538 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2539 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2540 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2541 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2542 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2543 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2544 if (rsurfacepass == RSURFPASS_BACKGROUND)
2546 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2547 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2548 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2552 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2554 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2555 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2556 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2557 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2558 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2560 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2561 if (rsurface.rtlight)
2563 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2564 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2569 case RENDERPATH_D3D10:
2570 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2572 case RENDERPATH_D3D11:
2573 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2575 case RENDERPATH_GL20:
2576 case RENDERPATH_GLES2:
2577 if (!vid.useinterleavedarrays)
2579 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);
2580 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2581 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2582 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2583 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2584 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2585 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2586 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2590 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);
2591 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2593 R_SetupShader_SetPermutationGLSL(mode, permutation);
2594 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2595 if (mode == SHADERMODE_LIGHTSOURCE)
2597 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2598 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2599 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2600 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2601 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2602 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);
2604 // additive passes are only darkened by fog, not tinted
2605 if (r_glsl_permutation->loc_FogColor >= 0)
2606 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2607 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2611 if (mode == SHADERMODE_FLATCOLOR)
2613 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2615 else if (mode == SHADERMODE_LIGHTDIRECTION)
2617 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]);
2618 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]);
2619 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);
2620 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);
2621 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);
2622 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]);
2623 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]);
2627 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]);
2628 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]);
2629 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);
2630 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);
2631 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);
2633 // additive passes are only darkened by fog, not tinted
2634 if (r_glsl_permutation->loc_FogColor >= 0)
2636 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2637 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2639 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2641 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);
2642 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]);
2643 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]);
2644 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]);
2645 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]);
2646 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2647 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2648 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2649 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]);
2651 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2652 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2653 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2654 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]);
2655 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]);
2657 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2658 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));
2659 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2660 if (r_glsl_permutation->loc_Color_Pants >= 0)
2662 if (rsurface.texture->pantstexture)
2663 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2665 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2667 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2669 if (rsurface.texture->shirttexture)
2670 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2672 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2674 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]);
2675 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2676 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2677 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2678 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));
2679 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]);
2680 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2681 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);}
2682 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2684 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2685 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2686 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2687 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2688 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2689 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2690 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2691 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2692 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2693 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2694 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2695 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2696 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2697 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2698 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);
2699 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2700 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2701 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2702 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2703 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2704 if (rsurfacepass == RSURFPASS_BACKGROUND)
2706 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);
2707 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);
2708 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);
2712 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);
2714 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2715 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2716 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2717 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2718 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2720 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2721 if (rsurface.rtlight)
2723 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2724 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2727 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2730 case RENDERPATH_GL13:
2731 case RENDERPATH_GL11:
2733 case RENDERPATH_SOFT:
2734 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);
2735 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2736 R_SetupShader_SetPermutationSoft(mode, permutation);
2737 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2738 if (mode == SHADERMODE_LIGHTSOURCE)
2740 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2741 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2742 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2743 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2744 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2745 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2747 // additive passes are only darkened by fog, not tinted
2748 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2749 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2753 if (mode == SHADERMODE_FLATCOLOR)
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2757 else if (mode == SHADERMODE_LIGHTDIRECTION)
2759 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]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2761 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);
2762 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);
2763 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2764 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]);
2765 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2769 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2771 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);
2772 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);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775 // additive passes are only darkened by fog, not tinted
2776 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2780 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);
2781 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2782 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2783 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]);
2784 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]);
2785 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2786 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2787 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2788 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2790 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2791 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2792 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2793 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2794 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]);
2796 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2797 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));
2798 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2799 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2801 if (rsurface.texture->pantstexture)
2802 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2804 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2806 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2808 if (rsurface.texture->shirttexture)
2809 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2811 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2813 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2814 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2815 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2816 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2817 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));
2818 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2819 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2821 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2822 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2823 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2824 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2825 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2826 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2827 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2828 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2829 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2830 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2831 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2832 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2833 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2834 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2835 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2836 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2837 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2838 if (rsurfacepass == RSURFPASS_BACKGROUND)
2840 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2841 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2842 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2846 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2848 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2849 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2850 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2851 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2852 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2854 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2855 if (rsurface.rtlight)
2857 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2858 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2865 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2867 // select a permutation of the lighting shader appropriate to this
2868 // combination of texture, entity, light source, and fogging, only use the
2869 // minimum features necessary to avoid wasting rendering time in the
2870 // fragment shader on features that are not being used
2871 unsigned int permutation = 0;
2872 unsigned int mode = 0;
2873 const float *lightcolorbase = rtlight->currentcolor;
2874 float ambientscale = rtlight->ambientscale;
2875 float diffusescale = rtlight->diffusescale;
2876 float specularscale = rtlight->specularscale;
2877 // this is the location of the light in view space
2878 vec3_t viewlightorigin;
2879 // this transforms from view space (camera) to light space (cubemap)
2880 matrix4x4_t viewtolight;
2881 matrix4x4_t lighttoview;
2882 float viewtolight16f[16];
2883 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2885 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2886 if (rtlight->currentcubemap != r_texture_whitecube)
2887 permutation |= SHADERPERMUTATION_CUBEFILTER;
2888 if (diffusescale > 0)
2889 permutation |= SHADERPERMUTATION_DIFFUSE;
2890 if (specularscale > 0)
2891 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2892 if (r_shadow_usingshadowmap2d)
2894 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2895 if (r_shadow_shadowmapvsdct)
2896 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2898 if (r_shadow_shadowmapsampler)
2899 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2900 if (r_shadow_shadowmappcf > 1)
2901 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2902 else if (r_shadow_shadowmappcf)
2903 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2905 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2906 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2907 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2908 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2909 switch(vid.renderpath)
2911 case RENDERPATH_D3D9:
2913 R_SetupShader_SetPermutationHLSL(mode, permutation);
2914 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2915 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2916 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2917 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2918 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2919 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2920 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2921 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2922 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2923 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2925 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2926 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2927 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2928 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2929 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2930 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2933 case RENDERPATH_D3D10:
2934 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2936 case RENDERPATH_D3D11:
2937 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2939 case RENDERPATH_GL20:
2940 case RENDERPATH_GLES2:
2941 R_SetupShader_SetPermutationGLSL(mode, permutation);
2942 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2943 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2944 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);
2945 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);
2946 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);
2947 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]);
2948 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]);
2949 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));
2950 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]);
2951 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2953 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2954 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2955 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2956 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2957 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2958 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2960 case RENDERPATH_GL13:
2961 case RENDERPATH_GL11:
2963 case RENDERPATH_SOFT:
2964 R_SetupShader_SetPermutationGLSL(mode, permutation);
2965 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2966 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2967 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2968 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2969 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2970 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2971 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]);
2972 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));
2973 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2974 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2976 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2977 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2978 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2979 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2980 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2981 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2986 #define SKINFRAME_HASH 1024
2990 int loadsequence; // incremented each level change
2991 memexpandablearray_t array;
2992 skinframe_t *hash[SKINFRAME_HASH];
2995 r_skinframe_t r_skinframe;
2997 void R_SkinFrame_PrepareForPurge(void)
2999 r_skinframe.loadsequence++;
3000 // wrap it without hitting zero
3001 if (r_skinframe.loadsequence >= 200)
3002 r_skinframe.loadsequence = 1;
3005 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3009 // mark the skinframe as used for the purging code
3010 skinframe->loadsequence = r_skinframe.loadsequence;
3013 void R_SkinFrame_Purge(void)
3017 for (i = 0;i < SKINFRAME_HASH;i++)
3019 for (s = r_skinframe.hash[i];s;s = s->next)
3021 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3023 if (s->merged == s->base)
3025 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3026 R_PurgeTexture(s->stain );s->stain = NULL;
3027 R_PurgeTexture(s->merged);s->merged = NULL;
3028 R_PurgeTexture(s->base );s->base = NULL;
3029 R_PurgeTexture(s->pants );s->pants = NULL;
3030 R_PurgeTexture(s->shirt );s->shirt = NULL;
3031 R_PurgeTexture(s->nmap );s->nmap = NULL;
3032 R_PurgeTexture(s->gloss );s->gloss = NULL;
3033 R_PurgeTexture(s->glow );s->glow = NULL;
3034 R_PurgeTexture(s->fog );s->fog = NULL;
3035 R_PurgeTexture(s->reflect);s->reflect = NULL;
3036 s->loadsequence = 0;
3042 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3044 char basename[MAX_QPATH];
3046 Image_StripImageExtension(name, basename, sizeof(basename));
3048 if( last == NULL ) {
3050 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3051 item = r_skinframe.hash[hashindex];
3056 // linearly search through the hash bucket
3057 for( ; item ; item = item->next ) {
3058 if( !strcmp( item->basename, basename ) ) {
3065 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3069 char basename[MAX_QPATH];
3071 Image_StripImageExtension(name, basename, sizeof(basename));
3073 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3074 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3075 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3079 rtexture_t *dyntexture;
3080 // check whether its a dynamic texture
3081 dyntexture = CL_GetDynTexture( basename );
3082 if (!add && !dyntexture)
3084 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3085 memset(item, 0, sizeof(*item));
3086 strlcpy(item->basename, basename, sizeof(item->basename));
3087 item->base = dyntexture; // either NULL or dyntexture handle
3088 item->textureflags = textureflags;
3089 item->comparewidth = comparewidth;
3090 item->compareheight = compareheight;
3091 item->comparecrc = comparecrc;
3092 item->next = r_skinframe.hash[hashindex];
3093 r_skinframe.hash[hashindex] = item;
3095 else if( item->base == NULL )
3097 rtexture_t *dyntexture;
3098 // check whether its a dynamic texture
3099 // 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]
3100 dyntexture = CL_GetDynTexture( basename );
3101 item->base = dyntexture; // either NULL or dyntexture handle
3104 R_SkinFrame_MarkUsed(item);
3108 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3110 unsigned long long avgcolor[5], wsum; \
3118 for(pix = 0; pix < cnt; ++pix) \
3121 for(comp = 0; comp < 3; ++comp) \
3123 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3126 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3128 for(comp = 0; comp < 3; ++comp) \
3129 avgcolor[comp] += getpixel * w; \
3132 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3133 avgcolor[4] += getpixel; \
3135 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3137 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3138 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3139 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3140 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3143 extern cvar_t gl_picmip;
3144 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3147 unsigned char *pixels;
3148 unsigned char *bumppixels;
3149 unsigned char *basepixels = NULL;
3150 int basepixels_width = 0;
3151 int basepixels_height = 0;
3152 skinframe_t *skinframe;
3153 rtexture_t *ddsbase = NULL;
3154 qboolean ddshasalpha = false;
3155 float ddsavgcolor[4];
3156 char basename[MAX_QPATH];
3157 int miplevel = R_PicmipForFlags(textureflags);
3158 int savemiplevel = miplevel;
3161 if (cls.state == ca_dedicated)
3164 // return an existing skinframe if already loaded
3165 // if loading of the first image fails, don't make a new skinframe as it
3166 // would cause all future lookups of this to be missing
3167 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3168 if (skinframe && skinframe->base)
3171 Image_StripImageExtension(name, basename, sizeof(basename));
3173 // check for DDS texture file first
3174 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3176 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3177 if (basepixels == NULL)
3181 // FIXME handle miplevel
3183 if (developer_loading.integer)
3184 Con_Printf("loading skin \"%s\"\n", name);
3186 // we've got some pixels to store, so really allocate this new texture now
3188 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3189 skinframe->stain = NULL;
3190 skinframe->merged = NULL;
3191 skinframe->base = NULL;
3192 skinframe->pants = NULL;
3193 skinframe->shirt = NULL;
3194 skinframe->nmap = NULL;
3195 skinframe->gloss = NULL;
3196 skinframe->glow = NULL;
3197 skinframe->fog = NULL;
3198 skinframe->reflect = NULL;
3199 skinframe->hasalpha = false;
3203 skinframe->base = ddsbase;
3204 skinframe->hasalpha = ddshasalpha;
3205 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3206 if (r_loadfog && skinframe->hasalpha)
3207 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3208 //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]);
3212 basepixels_width = image_width;
3213 basepixels_height = image_height;
3214 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);
3215 if (textureflags & TEXF_ALPHA)
3217 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3219 if (basepixels[j] < 255)
3221 skinframe->hasalpha = true;
3225 if (r_loadfog && skinframe->hasalpha)
3227 // has transparent pixels
3228 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3229 for (j = 0;j < image_width * image_height * 4;j += 4)
3234 pixels[j+3] = basepixels[j+3];
3236 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);
3240 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3241 //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]);
3242 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3243 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3244 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3245 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3250 mymiplevel = savemiplevel;
3251 if (r_loadnormalmap)
3252 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);
3253 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3255 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3256 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3257 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3258 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3261 // _norm is the name used by tenebrae and has been adopted as standard
3262 if (r_loadnormalmap && skinframe->nmap == NULL)
3264 mymiplevel = savemiplevel;
3265 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3267 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);
3271 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3273 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3274 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3275 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);
3277 Mem_Free(bumppixels);
3279 else if (r_shadow_bumpscale_basetexture.value > 0)
3281 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3282 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3283 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);
3286 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3287 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3290 // _luma is supported only for tenebrae compatibility
3291 // _glow is the preferred name
3292 mymiplevel = savemiplevel;
3293 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))))
3295 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);
3296 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3297 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3298 Mem_Free(pixels);pixels = NULL;
3301 mymiplevel = savemiplevel;
3302 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3304 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);
3305 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3306 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3311 mymiplevel = savemiplevel;
3312 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3314 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);
3315 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3316 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3321 mymiplevel = savemiplevel;
3322 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3324 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);
3325 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3326 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3331 mymiplevel = savemiplevel;
3332 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3334 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);
3335 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3336 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3342 Mem_Free(basepixels);
3347 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3348 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3351 unsigned char *temp1, *temp2;
3352 skinframe_t *skinframe;
3354 if (cls.state == ca_dedicated)
3357 // if already loaded just return it, otherwise make a new skinframe
3358 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3359 if (skinframe && skinframe->base)
3362 skinframe->stain = NULL;
3363 skinframe->merged = NULL;
3364 skinframe->base = NULL;
3365 skinframe->pants = NULL;
3366 skinframe->shirt = NULL;
3367 skinframe->nmap = NULL;
3368 skinframe->gloss = NULL;
3369 skinframe->glow = NULL;
3370 skinframe->fog = NULL;
3371 skinframe->reflect = NULL;
3372 skinframe->hasalpha = false;
3374 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3378 if (developer_loading.integer)
3379 Con_Printf("loading 32bit skin \"%s\"\n", name);
3381 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3383 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3384 temp2 = temp1 + width * height * 4;
3385 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3386 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);
3389 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3390 if (textureflags & TEXF_ALPHA)
3392 for (i = 3;i < width * height * 4;i += 4)
3394 if (skindata[i] < 255)
3396 skinframe->hasalpha = true;
3400 if (r_loadfog && skinframe->hasalpha)
3402 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3403 memcpy(fogpixels, skindata, width * height * 4);
3404 for (i = 0;i < width * height * 4;i += 4)
3405 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3406 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3407 Mem_Free(fogpixels);
3411 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3412 //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]);
3417 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3421 skinframe_t *skinframe;
3423 if (cls.state == ca_dedicated)
3426 // if already loaded just return it, otherwise make a new skinframe
3427 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3428 if (skinframe && skinframe->base)
3431 skinframe->stain = NULL;
3432 skinframe->merged = NULL;
3433 skinframe->base = NULL;
3434 skinframe->pants = NULL;
3435 skinframe->shirt = NULL;
3436 skinframe->nmap = NULL;
3437 skinframe->gloss = NULL;
3438 skinframe->glow = NULL;
3439 skinframe->fog = NULL;
3440 skinframe->reflect = NULL;
3441 skinframe->hasalpha = false;
3443 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3447 if (developer_loading.integer)
3448 Con_Printf("loading quake skin \"%s\"\n", name);
3450 // 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)
3451 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3452 memcpy(skinframe->qpixels, skindata, width*height);
3453 skinframe->qwidth = width;
3454 skinframe->qheight = height;
3457 for (i = 0;i < width * height;i++)
3458 featuresmask |= palette_featureflags[skindata[i]];
3460 skinframe->hasalpha = false;
3461 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3462 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3463 skinframe->qgeneratemerged = true;
3464 skinframe->qgeneratebase = skinframe->qhascolormapping;
3465 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3467 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3468 //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]);
3473 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3477 unsigned char *skindata;
3479 if (!skinframe->qpixels)
3482 if (!skinframe->qhascolormapping)
3483 colormapped = false;
3487 if (!skinframe->qgeneratebase)
3492 if (!skinframe->qgeneratemerged)
3496 width = skinframe->qwidth;
3497 height = skinframe->qheight;
3498 skindata = skinframe->qpixels;
3500 if (skinframe->qgeneratenmap)
3502 unsigned char *temp1, *temp2;
3503 skinframe->qgeneratenmap = false;
3504 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3505 temp2 = temp1 + width * height * 4;
3506 // use either a custom palette or the quake palette
3507 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3508 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3509 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);
3513 if (skinframe->qgenerateglow)
3515 skinframe->qgenerateglow = false;
3516 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3521 skinframe->qgeneratebase = false;
3522 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);
3523 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3524 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3528 skinframe->qgeneratemerged = false;
3529 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);
3532 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3534 Mem_Free(skinframe->qpixels);
3535 skinframe->qpixels = NULL;
3539 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)
3542 skinframe_t *skinframe;
3544 if (cls.state == ca_dedicated)
3547 // if already loaded just return it, otherwise make a new skinframe
3548 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3549 if (skinframe && skinframe->base)
3552 skinframe->stain = NULL;
3553 skinframe->merged = NULL;
3554 skinframe->base = NULL;
3555 skinframe->pants = NULL;
3556 skinframe->shirt = NULL;
3557 skinframe->nmap = NULL;
3558 skinframe->gloss = NULL;
3559 skinframe->glow = NULL;
3560 skinframe->fog = NULL;
3561 skinframe->reflect = NULL;
3562 skinframe->hasalpha = false;
3564 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3568 if (developer_loading.integer)
3569 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3571 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3572 if (textureflags & TEXF_ALPHA)
3574 for (i = 0;i < width * height;i++)
3576 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3578 skinframe->hasalpha = true;
3582 if (r_loadfog && skinframe->hasalpha)
3583 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3586 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3587 //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]);
3592 skinframe_t *R_SkinFrame_LoadMissing(void)
3594 skinframe_t *skinframe;
3596 if (cls.state == ca_dedicated)
3599 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3600 skinframe->stain = NULL;
3601 skinframe->merged = NULL;
3602 skinframe->base = NULL;
3603 skinframe->pants = NULL;
3604 skinframe->shirt = NULL;
3605 skinframe->nmap = NULL;
3606 skinframe->gloss = NULL;
3607 skinframe->glow = NULL;
3608 skinframe->fog = NULL;
3609 skinframe->reflect = NULL;
3610 skinframe->hasalpha = false;
3612 skinframe->avgcolor[0] = rand() / RAND_MAX;
3613 skinframe->avgcolor[1] = rand() / RAND_MAX;
3614 skinframe->avgcolor[2] = rand() / RAND_MAX;
3615 skinframe->avgcolor[3] = 1;
3620 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3621 typedef struct suffixinfo_s
3624 qboolean flipx, flipy, flipdiagonal;
3627 static suffixinfo_t suffix[3][6] =
3630 {"px", false, false, false},
3631 {"nx", false, false, false},
3632 {"py", false, false, false},
3633 {"ny", false, false, false},
3634 {"pz", false, false, false},
3635 {"nz", false, false, false}
3638 {"posx", false, false, false},
3639 {"negx", false, false, false},
3640 {"posy", false, false, false},
3641 {"negy", false, false, false},
3642 {"posz", false, false, false},
3643 {"negz", false, false, false}
3646 {"rt", true, false, true},
3647 {"lf", false, true, true},
3648 {"ft", true, true, false},
3649 {"bk", false, false, false},
3650 {"up", true, false, true},
3651 {"dn", true, false, true}
3655 static int componentorder[4] = {0, 1, 2, 3};
3657 rtexture_t *R_LoadCubemap(const char *basename)
3659 int i, j, cubemapsize;
3660 unsigned char *cubemappixels, *image_buffer;
3661 rtexture_t *cubemaptexture;
3663 // must start 0 so the first loadimagepixels has no requested width/height
3665 cubemappixels = NULL;
3666 cubemaptexture = NULL;
3667 // keep trying different suffix groups (posx, px, rt) until one loads
3668 for (j = 0;j < 3 && !cubemappixels;j++)
3670 // load the 6 images in the suffix group
3671 for (i = 0;i < 6;i++)
3673 // generate an image name based on the base and and suffix
3674 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3676 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3678 // an image loaded, make sure width and height are equal
3679 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3681 // if this is the first image to load successfully, allocate the cubemap memory
3682 if (!cubemappixels && image_width >= 1)
3684 cubemapsize = image_width;
3685 // note this clears to black, so unavailable sides are black
3686 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3688 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3690 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);
3693 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3695 Mem_Free(image_buffer);
3699 // if a cubemap loaded, upload it
3702 if (developer_loading.integer)
3703 Con_Printf("loading cubemap \"%s\"\n", basename);
3705 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3706 Mem_Free(cubemappixels);
3710 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3711 if (developer_loading.integer)
3713 Con_Printf("(tried tried images ");
3714 for (j = 0;j < 3;j++)
3715 for (i = 0;i < 6;i++)
3716 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3717 Con_Print(" and was unable to find any of them).\n");
3720 return cubemaptexture;
3723 rtexture_t *R_GetCubemap(const char *basename)
3726 for (i = 0;i < r_texture_numcubemaps;i++)
3727 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3728 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3729 if (i >= MAX_CUBEMAPS)
3730 return r_texture_whitecube;
3731 r_texture_numcubemaps++;
3732 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3733 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3734 return r_texture_cubemaps[i].texture;
3737 void R_FreeCubemaps(void)
3740 for (i = 0;i < r_texture_numcubemaps;i++)
3742 if (developer_loading.integer)
3743 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3744 if (r_texture_cubemaps[i].texture)
3745 R_FreeTexture(r_texture_cubemaps[i].texture);
3747 r_texture_numcubemaps = 0;
3750 void R_Main_FreeViewCache(void)
3752 if (r_refdef.viewcache.entityvisible)
3753 Mem_Free(r_refdef.viewcache.entityvisible);
3754 if (r_refdef.viewcache.world_pvsbits)
3755 Mem_Free(r_refdef.viewcache.world_pvsbits);
3756 if (r_refdef.viewcache.world_leafvisible)
3757 Mem_Free(r_refdef.viewcache.world_leafvisible);
3758 if (r_refdef.viewcache.world_surfacevisible)
3759 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3760 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3763 void R_Main_ResizeViewCache(void)
3765 int numentities = r_refdef.scene.numentities;
3766 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3767 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3768 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3769 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3770 if (r_refdef.viewcache.maxentities < numentities)
3772 r_refdef.viewcache.maxentities = numentities;
3773 if (r_refdef.viewcache.entityvisible)
3774 Mem_Free(r_refdef.viewcache.entityvisible);
3775 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3777 if (r_refdef.viewcache.world_numclusters != numclusters)
3779 r_refdef.viewcache.world_numclusters = numclusters;
3780 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3781 if (r_refdef.viewcache.world_pvsbits)
3782 Mem_Free(r_refdef.viewcache.world_pvsbits);
3783 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3785 if (r_refdef.viewcache.world_numleafs != numleafs)
3787 r_refdef.viewcache.world_numleafs = numleafs;
3788 if (r_refdef.viewcache.world_leafvisible)
3789 Mem_Free(r_refdef.viewcache.world_leafvisible);
3790 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3792 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3794 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3795 if (r_refdef.viewcache.world_surfacevisible)
3796 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3797 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3801 extern rtexture_t *loadingscreentexture;
3802 void gl_main_start(void)
3804 loadingscreentexture = NULL;
3805 r_texture_blanknormalmap = NULL;
3806 r_texture_white = NULL;
3807 r_texture_grey128 = NULL;
3808 r_texture_black = NULL;
3809 r_texture_whitecube = NULL;
3810 r_texture_normalizationcube = NULL;
3811 r_texture_fogattenuation = NULL;
3812 r_texture_fogheighttexture = NULL;
3813 r_texture_gammaramps = NULL;
3814 r_texture_numcubemaps = 0;
3816 r_loaddds = r_texture_dds_load.integer != 0;
3817 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3819 switch(vid.renderpath)
3821 case RENDERPATH_GL20:
3822 case RENDERPATH_D3D9:
3823 case RENDERPATH_D3D10:
3824 case RENDERPATH_D3D11:
3825 case RENDERPATH_SOFT:
3826 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3827 Cvar_SetValueQuick(&gl_combine, 1);
3828 Cvar_SetValueQuick(&r_glsl, 1);
3829 r_loadnormalmap = true;
3833 case RENDERPATH_GL13:
3834 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3835 Cvar_SetValueQuick(&gl_combine, 1);
3836 Cvar_SetValueQuick(&r_glsl, 0);
3837 r_loadnormalmap = false;
3838 r_loadgloss = false;
3841 case RENDERPATH_GL11:
3842 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3843 Cvar_SetValueQuick(&gl_combine, 0);
3844 Cvar_SetValueQuick(&r_glsl, 0);
3845 r_loadnormalmap = false;
3846 r_loadgloss = false;
3849 case RENDERPATH_GLES2:
3850 Cvar_SetValueQuick(&r_textureunits, 1);
3851 Cvar_SetValueQuick(&gl_combine, 1);
3852 Cvar_SetValueQuick(&r_glsl, 1);
3853 r_loadnormalmap = true;
3854 r_loadgloss = false;
3860 R_FrameData_Reset();
3864 memset(r_queries, 0, sizeof(r_queries));
3866 r_qwskincache = NULL;
3867 r_qwskincache_size = 0;
3869 // due to caching of texture_t references, the collision cache must be reset
3870 Collision_Cache_Reset(true);
3872 // set up r_skinframe loading system for textures
3873 memset(&r_skinframe, 0, sizeof(r_skinframe));
3874 r_skinframe.loadsequence = 1;
3875 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3877 r_main_texturepool = R_AllocTexturePool();
3878 R_BuildBlankTextures();
3880 if (vid.support.arb_texture_cube_map)
3883 R_BuildNormalizationCube();
3885 r_texture_fogattenuation = NULL;
3886 r_texture_fogheighttexture = NULL;
3887 r_texture_gammaramps = NULL;
3888 //r_texture_fogintensity = NULL;
3889 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3890 memset(&r_waterstate, 0, sizeof(r_waterstate));
3891 r_glsl_permutation = NULL;
3892 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3893 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3894 glslshaderstring = NULL;
3896 r_hlsl_permutation = NULL;
3897 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3898 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3900 hlslshaderstring = NULL;
3901 memset(&r_svbsp, 0, sizeof (r_svbsp));
3903 r_refdef.fogmasktable_density = 0;
3906 void gl_main_shutdown(void)
3909 R_FrameData_Reset();
3911 R_Main_FreeViewCache();
3913 switch(vid.renderpath)
3915 case RENDERPATH_GL11:
3916 case RENDERPATH_GL13:
3917 case RENDERPATH_GL20:
3918 case RENDERPATH_GLES2:
3920 qglDeleteQueriesARB(r_maxqueries, r_queries);
3922 case RENDERPATH_D3D9:
3923 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3925 case RENDERPATH_D3D10:
3926 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3928 case RENDERPATH_D3D11:
3929 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3931 case RENDERPATH_SOFT:
3937 memset(r_queries, 0, sizeof(r_queries));
3939 r_qwskincache = NULL;
3940 r_qwskincache_size = 0;
3942 // clear out the r_skinframe state
3943 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3944 memset(&r_skinframe, 0, sizeof(r_skinframe));
3947 Mem_Free(r_svbsp.nodes);
3948 memset(&r_svbsp, 0, sizeof (r_svbsp));
3949 R_FreeTexturePool(&r_main_texturepool);
3950 loadingscreentexture = NULL;
3951 r_texture_blanknormalmap = NULL;
3952 r_texture_white = NULL;
3953 r_texture_grey128 = NULL;
3954 r_texture_black = NULL;
3955 r_texture_whitecube = NULL;
3956 r_texture_normalizationcube = NULL;
3957 r_texture_fogattenuation = NULL;
3958 r_texture_fogheighttexture = NULL;
3959 r_texture_gammaramps = NULL;
3960 r_texture_numcubemaps = 0;
3961 //r_texture_fogintensity = NULL;
3962 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3963 memset(&r_waterstate, 0, sizeof(r_waterstate));
3966 r_glsl_permutation = NULL;
3967 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3968 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3969 glslshaderstring = NULL;
3971 r_hlsl_permutation = NULL;
3972 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3973 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3975 hlslshaderstring = NULL;
3978 extern void CL_ParseEntityLump(char *entitystring);
3979 void gl_main_newmap(void)
3981 // FIXME: move this code to client
3982 char *entities, entname[MAX_QPATH];
3984 Mem_Free(r_qwskincache);
3985 r_qwskincache = NULL;
3986 r_qwskincache_size = 0;
3989 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3990 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3992 CL_ParseEntityLump(entities);
3996 if (cl.worldmodel->brush.entities)
3997 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3999 R_Main_FreeViewCache();
4001 R_FrameData_Reset();
4004 void GL_Main_Init(void)
4006 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4008 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4009 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4010 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4011 if (gamemode == GAME_NEHAHRA)
4013 Cvar_RegisterVariable (&gl_fogenable);
4014 Cvar_RegisterVariable (&gl_fogdensity);
4015 Cvar_RegisterVariable (&gl_fogred);
4016 Cvar_RegisterVariable (&gl_foggreen);
4017 Cvar_RegisterVariable (&gl_fogblue);
4018 Cvar_RegisterVariable (&gl_fogstart);
4019 Cvar_RegisterVariable (&gl_fogend);
4020 Cvar_RegisterVariable (&gl_skyclip);
4022 Cvar_RegisterVariable(&r_motionblur);
4023 Cvar_RegisterVariable(&r_motionblur_maxblur);
4024 Cvar_RegisterVariable(&r_motionblur_bmin);
4025 Cvar_RegisterVariable(&r_motionblur_vmin);
4026 Cvar_RegisterVariable(&r_motionblur_vmax);
4027 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4028 Cvar_RegisterVariable(&r_motionblur_randomize);
4029 Cvar_RegisterVariable(&r_damageblur);
4030 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4031 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4032 Cvar_RegisterVariable(&r_equalize_entities_by);
4033 Cvar_RegisterVariable(&r_equalize_entities_to);
4034 Cvar_RegisterVariable(&r_depthfirst);
4035 Cvar_RegisterVariable(&r_useinfinitefarclip);
4036 Cvar_RegisterVariable(&r_farclip_base);
4037 Cvar_RegisterVariable(&r_farclip_world);
4038 Cvar_RegisterVariable(&r_nearclip);
4039 Cvar_RegisterVariable(&r_showbboxes);
4040 Cvar_RegisterVariable(&r_showsurfaces);
4041 Cvar_RegisterVariable(&r_showtris);
4042 Cvar_RegisterVariable(&r_shownormals);
4043 Cvar_RegisterVariable(&r_showlighting);
4044 Cvar_RegisterVariable(&r_showshadowvolumes);
4045 Cvar_RegisterVariable(&r_showcollisionbrushes);
4046 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4047 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4048 Cvar_RegisterVariable(&r_showdisabledepthtest);
4049 Cvar_RegisterVariable(&r_drawportals);
4050 Cvar_RegisterVariable(&r_drawentities);
4051 Cvar_RegisterVariable(&r_draw2d);
4052 Cvar_RegisterVariable(&r_drawworld);
4053 Cvar_RegisterVariable(&r_cullentities_trace);
4054 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4055 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4056 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4057 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4058 Cvar_RegisterVariable(&r_drawviewmodel);
4059 Cvar_RegisterVariable(&r_drawexteriormodel);
4060 Cvar_RegisterVariable(&r_speeds);
4061 Cvar_RegisterVariable(&r_fullbrights);
4062 Cvar_RegisterVariable(&r_wateralpha);
4063 Cvar_RegisterVariable(&r_dynamic);
4064 Cvar_RegisterVariable(&r_fakelight);
4065 Cvar_RegisterVariable(&r_fakelight_intensity);
4066 Cvar_RegisterVariable(&r_fullbright);
4067 Cvar_RegisterVariable(&r_shadows);
4068 Cvar_RegisterVariable(&r_shadows_darken);
4069 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4070 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4071 Cvar_RegisterVariable(&r_shadows_throwdistance);
4072 Cvar_RegisterVariable(&r_shadows_throwdirection);
4073 Cvar_RegisterVariable(&r_shadows_focus);
4074 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4075 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4076 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4077 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4078 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4079 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4080 Cvar_RegisterVariable(&r_fog_exp2);
4081 Cvar_RegisterVariable(&r_drawfog);
4082 Cvar_RegisterVariable(&r_transparentdepthmasking);
4083 Cvar_RegisterVariable(&r_texture_dds_load);
4084 Cvar_RegisterVariable(&r_texture_dds_save);
4085 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4086 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4087 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4088 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4089 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4090 Cvar_RegisterVariable(&r_textureunits);
4091 Cvar_RegisterVariable(&gl_combine);
4092 Cvar_RegisterVariable(&r_glsl);
4093 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4094 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4095 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4096 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4097 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4098 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4099 Cvar_RegisterVariable(&r_glsl_postprocess);
4100 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4101 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4102 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4103 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4104 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4105 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4106 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4107 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4109 Cvar_RegisterVariable(&r_water);
4110 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4111 Cvar_RegisterVariable(&r_water_clippingplanebias);
4112 Cvar_RegisterVariable(&r_water_refractdistort);
4113 Cvar_RegisterVariable(&r_water_reflectdistort);
4114 Cvar_RegisterVariable(&r_water_scissormode);
4115 Cvar_RegisterVariable(&r_lerpsprites);
4116 Cvar_RegisterVariable(&r_lerpmodels);
4117 Cvar_RegisterVariable(&r_lerplightstyles);
4118 Cvar_RegisterVariable(&r_waterscroll);
4119 Cvar_RegisterVariable(&r_bloom);
4120 Cvar_RegisterVariable(&r_bloom_colorscale);
4121 Cvar_RegisterVariable(&r_bloom_brighten);
4122 Cvar_RegisterVariable(&r_bloom_blur);
4123 Cvar_RegisterVariable(&r_bloom_resolution);
4124 Cvar_RegisterVariable(&r_bloom_colorexponent);
4125 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4126 Cvar_RegisterVariable(&r_hdr);
4127 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4128 Cvar_RegisterVariable(&r_hdr_glowintensity);
4129 Cvar_RegisterVariable(&r_hdr_range);
4130 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4131 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4132 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4133 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4134 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4135 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4136 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4137 Cvar_RegisterVariable(&developer_texturelogging);
4138 Cvar_RegisterVariable(&gl_lightmaps);
4139 Cvar_RegisterVariable(&r_test);
4140 Cvar_RegisterVariable(&r_glsl_saturation);
4141 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4142 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4143 Cvar_RegisterVariable(&r_framedatasize);
4144 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4145 Cvar_SetValue("r_fullbrights", 0);
4146 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4148 Cvar_RegisterVariable(&r_track_sprites);
4149 Cvar_RegisterVariable(&r_track_sprites_flags);
4150 Cvar_RegisterVariable(&r_track_sprites_scalew);
4151 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4152 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4153 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4154 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4155 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4158 extern void R_Textures_Init(void);
4159 extern void GL_Draw_Init(void);
4160 extern void GL_Main_Init(void);
4161 extern void R_Shadow_Init(void);
4162 extern void R_Sky_Init(void);
4163 extern void GL_Surf_Init(void);
4164 extern void R_Particles_Init(void);
4165 extern void R_Explosion_Init(void);
4166 extern void gl_backend_init(void);
4167 extern void Sbar_Init(void);
4168 extern void R_LightningBeams_Init(void);
4169 extern void Mod_RenderInit(void);
4170 extern void Font_Init(void);
4172 void Render_Init(void)
4185 R_LightningBeams_Init();
4194 extern char *ENGINE_EXTENSIONS;
4197 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4198 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4199 gl_version = (const char *)qglGetString(GL_VERSION);
4200 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4204 if (!gl_platformextensions)
4205 gl_platformextensions = "";
4207 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4208 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4209 Con_Printf("GL_VERSION: %s\n", gl_version);
4210 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4211 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4213 VID_CheckExtensions();
4215 // LordHavoc: report supported extensions
4216 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4218 // clear to black (loading plaque will be seen over this)
4219 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4222 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4226 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4228 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4231 p = r_refdef.view.frustum + i;
4236 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4240 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4244 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4248 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4252 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4256 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4260 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4264 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4272 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4276 for (i = 0;i < numplanes;i++)
4283 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4287 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4291 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4295 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4299 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4303 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4307 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4311 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4319 //==================================================================================
4321 // LordHavoc: this stores temporary data used within the same frame
4323 typedef struct r_framedata_mem_s
4325 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4326 size_t size; // how much usable space
4327 size_t current; // how much space in use
4328 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4329 size_t wantedsize; // how much space was allocated
4330 unsigned char *data; // start of real data (16byte aligned)
4334 static r_framedata_mem_t *r_framedata_mem;
4336 void R_FrameData_Reset(void)
4338 while (r_framedata_mem)
4340 r_framedata_mem_t *next = r_framedata_mem->purge;
4341 Mem_Free(r_framedata_mem);
4342 r_framedata_mem = next;
4346 void R_FrameData_Resize(void)
4349 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4350 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4351 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4353 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4354 newmem->wantedsize = wantedsize;
4355 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4356 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4357 newmem->current = 0;
4359 newmem->purge = r_framedata_mem;
4360 r_framedata_mem = newmem;
4364 void R_FrameData_NewFrame(void)
4366 R_FrameData_Resize();
4367 if (!r_framedata_mem)
4369 // if we ran out of space on the last frame, free the old memory now
4370 while (r_framedata_mem->purge)
4372 // repeatedly remove the second item in the list, leaving only head
4373 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4374 Mem_Free(r_framedata_mem->purge);
4375 r_framedata_mem->purge = next;
4377 // reset the current mem pointer
4378 r_framedata_mem->current = 0;
4379 r_framedata_mem->mark = 0;
4382 void *R_FrameData_Alloc(size_t size)
4386 // align to 16 byte boundary - the data pointer is already aligned, so we
4387 // only need to ensure the size of every allocation is also aligned
4388 size = (size + 15) & ~15;
4390 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4392 // emergency - we ran out of space, allocate more memory
4393 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4394 R_FrameData_Resize();
4397 data = r_framedata_mem->data + r_framedata_mem->current;
4398 r_framedata_mem->current += size;
4400 // count the usage for stats
4401 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4402 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4404 return (void *)data;
4407 void *R_FrameData_Store(size_t size, void *data)
4409 void *d = R_FrameData_Alloc(size);
4411 memcpy(d, data, size);
4415 void R_FrameData_SetMark(void)
4417 if (!r_framedata_mem)
4419 r_framedata_mem->mark = r_framedata_mem->current;
4422 void R_FrameData_ReturnToMark(void)
4424 if (!r_framedata_mem)
4426 r_framedata_mem->current = r_framedata_mem->mark;
4429 //==================================================================================
4431 // LordHavoc: animcache originally written by Echon, rewritten since then
4434 * Animation cache prevents re-generating mesh data for an animated model
4435 * multiple times in one frame for lighting, shadowing, reflections, etc.
4438 void R_AnimCache_Free(void)
4442 void R_AnimCache_ClearCache(void)
4445 entity_render_t *ent;
4447 for (i = 0;i < r_refdef.scene.numentities;i++)
4449 ent = r_refdef.scene.entities[i];
4450 ent->animcache_vertex3f = NULL;
4451 ent->animcache_normal3f = NULL;
4452 ent->animcache_svector3f = NULL;
4453 ent->animcache_tvector3f = NULL;
4454 ent->animcache_vertexmesh = NULL;
4455 ent->animcache_vertex3fbuffer = NULL;
4456 ent->animcache_vertexmeshbuffer = NULL;
4460 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4464 // check if we need the meshbuffers
4465 if (!vid.useinterleavedarrays)
4468 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4469 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4470 // TODO: upload vertex3f buffer?
4471 if (ent->animcache_vertexmesh)
4473 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4474 for (i = 0;i < numvertices;i++)
4475 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4476 if (ent->animcache_svector3f)
4477 for (i = 0;i < numvertices;i++)
4478 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4479 if (ent->animcache_tvector3f)
4480 for (i = 0;i < numvertices;i++)
4481 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4482 if (ent->animcache_normal3f)
4483 for (i = 0;i < numvertices;i++)
4484 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4485 // TODO: upload vertexmeshbuffer?
4489 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4491 dp_model_t *model = ent->model;
4493 // see if it's already cached this frame
4494 if (ent->animcache_vertex3f)
4496 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4497 if (wantnormals || wanttangents)
4499 if (ent->animcache_normal3f)
4500 wantnormals = false;
4501 if (ent->animcache_svector3f)
4502 wanttangents = false;
4503 if (wantnormals || wanttangents)
4505 numvertices = model->surfmesh.num_vertices;
4507 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4510 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4511 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4513 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4514 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4520 // see if this ent is worth caching
4521 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4523 // get some memory for this entity and generate mesh data
4524 numvertices = model->surfmesh.num_vertices;
4525 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4527 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4530 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4534 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4539 void R_AnimCache_CacheVisibleEntities(void)
4542 qboolean wantnormals = true;
4543 qboolean wanttangents = !r_showsurfaces.integer;
4545 switch(vid.renderpath)
4547 case RENDERPATH_GL20:
4548 case RENDERPATH_D3D9:
4549 case RENDERPATH_D3D10:
4550 case RENDERPATH_D3D11:
4551 case RENDERPATH_GLES2:
4553 case RENDERPATH_GL13:
4554 case RENDERPATH_GL11:
4555 wanttangents = false;
4557 case RENDERPATH_SOFT:
4561 if (r_shownormals.integer)
4562 wanttangents = wantnormals = true;
4564 // TODO: thread this
4565 // NOTE: R_PrepareRTLights() also caches entities
4567 for (i = 0;i < r_refdef.scene.numentities;i++)
4568 if (r_refdef.viewcache.entityvisible[i])
4569 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4572 //==================================================================================
4574 static void R_View_UpdateEntityLighting (void)
4577 entity_render_t *ent;
4578 vec3_t tempdiffusenormal, avg;
4579 vec_t f, fa, fd, fdd;
4580 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4582 for (i = 0;i < r_refdef.scene.numentities;i++)
4584 ent = r_refdef.scene.entities[i];
4586 // skip unseen models
4587 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4591 if (ent->model && ent->model->brush.num_leafs)
4593 // TODO: use modellight for r_ambient settings on world?
4594 VectorSet(ent->modellight_ambient, 0, 0, 0);
4595 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4596 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4600 // fetch the lighting from the worldmodel data
4601 VectorClear(ent->modellight_ambient);
4602 VectorClear(ent->modellight_diffuse);
4603 VectorClear(tempdiffusenormal);
4604 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4607 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4609 // complete lightning for lit sprites
4610 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4611 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4613 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4614 org[2] = org[2] + r_overheadsprites_pushback.value;
4615 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4618 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4620 if(ent->flags & RENDER_EQUALIZE)
4622 // first fix up ambient lighting...
4623 if(r_equalize_entities_minambient.value > 0)
4625 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4628 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4629 if(fa < r_equalize_entities_minambient.value * fd)
4632 // fa'/fd' = minambient
4633 // fa'+0.25*fd' = fa+0.25*fd
4635 // fa' = fd' * minambient
4636 // fd'*(0.25+minambient) = fa+0.25*fd
4638 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4639 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4641 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4642 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
4643 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4644 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4649 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4651 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4652 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4656 // adjust brightness and saturation to target
4657 avg[0] = avg[1] = avg[2] = fa / f;
4658 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4659 avg[0] = avg[1] = avg[2] = fd / f;
4660 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4666 VectorSet(ent->modellight_ambient, 1, 1, 1);
4668 // move the light direction into modelspace coordinates for lighting code
4669 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4670 if(VectorLength2(ent->modellight_lightdir) == 0)
4671 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4672 VectorNormalize(ent->modellight_lightdir);
4676 #define MAX_LINEOFSIGHTTRACES 64
4678 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4681 vec3_t boxmins, boxmaxs;
4684 dp_model_t *model = r_refdef.scene.worldmodel;
4686 if (!model || !model->brush.TraceLineOfSight)
4689 // expand the box a little
4690 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4691 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4692 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4693 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4694 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4695 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4697 // return true if eye is inside enlarged box
4698 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4702 VectorCopy(eye, start);
4703 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4704 if (model->brush.TraceLineOfSight(model, start, end))
4707 // try various random positions
4708 for (i = 0;i < numsamples;i++)
4710 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4711 if (model->brush.TraceLineOfSight(model, start, end))
4719 static void R_View_UpdateEntityVisible (void)
4724 entity_render_t *ent;
4726 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4727 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4728 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4729 : RENDER_EXTERIORMODEL;
4730 if (!r_drawviewmodel.integer)
4731 renderimask |= RENDER_VIEWMODEL;
4732 if (!r_drawexteriormodel.integer)
4733 renderimask |= RENDER_EXTERIORMODEL;
4734 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4736 // worldmodel can check visibility
4737 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4738 for (i = 0;i < r_refdef.scene.numentities;i++)
4740 ent = r_refdef.scene.entities[i];
4741 if (!(ent->flags & renderimask))
4742 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)))
4743 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))
4744 r_refdef.viewcache.entityvisible[i] = true;
4746 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4747 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4749 for (i = 0;i < r_refdef.scene.numentities;i++)
4751 ent = r_refdef.scene.entities[i];
4752 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4754 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4756 continue; // temp entities do pvs only
4757 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4758 ent->last_trace_visibility = realtime;
4759 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4760 r_refdef.viewcache.entityvisible[i] = 0;
4767 // no worldmodel or it can't check visibility
4768 for (i = 0;i < r_refdef.scene.numentities;i++)
4770 ent = r_refdef.scene.entities[i];
4771 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));
4776 /// only used if skyrendermasked, and normally returns false
4777 int R_DrawBrushModelsSky (void)
4780 entity_render_t *ent;
4783 for (i = 0;i < r_refdef.scene.numentities;i++)
4785 if (!r_refdef.viewcache.entityvisible[i])
4787 ent = r_refdef.scene.entities[i];
4788 if (!ent->model || !ent->model->DrawSky)
4790 ent->model->DrawSky(ent);
4796 static void R_DrawNoModel(entity_render_t *ent);
4797 static void R_DrawModels(void)
4800 entity_render_t *ent;
4802 for (i = 0;i < r_refdef.scene.numentities;i++)
4804 if (!r_refdef.viewcache.entityvisible[i])
4806 ent = r_refdef.scene.entities[i];
4807 r_refdef.stats.entities++;
4808 if (ent->model && ent->model->Draw != NULL)
4809 ent->model->Draw(ent);
4815 static void R_DrawModelsDepth(void)
4818 entity_render_t *ent;
4820 for (i = 0;i < r_refdef.scene.numentities;i++)
4822 if (!r_refdef.viewcache.entityvisible[i])
4824 ent = r_refdef.scene.entities[i];
4825 if (ent->model && ent->model->DrawDepth != NULL)
4826 ent->model->DrawDepth(ent);
4830 static void R_DrawModelsDebug(void)
4833 entity_render_t *ent;
4835 for (i = 0;i < r_refdef.scene.numentities;i++)
4837 if (!r_refdef.viewcache.entityvisible[i])
4839 ent = r_refdef.scene.entities[i];
4840 if (ent->model && ent->model->DrawDebug != NULL)
4841 ent->model->DrawDebug(ent);
4845 static void R_DrawModelsAddWaterPlanes(void)
4848 entity_render_t *ent;
4850 for (i = 0;i < r_refdef.scene.numentities;i++)
4852 if (!r_refdef.viewcache.entityvisible[i])
4854 ent = r_refdef.scene.entities[i];
4855 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4856 ent->model->DrawAddWaterPlanes(ent);
4860 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4862 if (r_hdr_irisadaptation.integer)
4866 vec3_t diffusenormal;
4871 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4872 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4873 brightness = max(0.0000001f, brightness);
4874 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4875 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4876 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4877 current = r_hdr_irisadaptation_value.value;
4879 current = min(current + adjust, goal);
4880 else if (current > goal)
4881 current = max(current - adjust, goal);
4882 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4883 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4885 else if (r_hdr_irisadaptation_value.value != 1.0f)
4886 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4889 static void R_View_SetFrustum(const int *scissor)
4892 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4893 vec3_t forward, left, up, origin, v;
4897 // flipped x coordinates (because x points left here)
4898 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4899 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4901 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4902 switch(vid.renderpath)
4904 case RENDERPATH_D3D9:
4905 case RENDERPATH_D3D10:
4906 case RENDERPATH_D3D11:
4907 case RENDERPATH_SOFT:
4908 // non-flipped y coordinates
4909 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4910 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4912 case RENDERPATH_GL11:
4913 case RENDERPATH_GL13:
4914 case RENDERPATH_GL20:
4915 case RENDERPATH_GLES2:
4916 // non-flipped y coordinates
4917 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4918 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4923 // we can't trust r_refdef.view.forward and friends in reflected scenes
4924 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4927 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4928 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4929 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4930 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4931 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4932 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4933 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4934 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4935 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4936 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4937 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4938 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4942 zNear = r_refdef.nearclip;
4943 nudge = 1.0 - 1.0 / (1<<23);
4944 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4945 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4946 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4947 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4948 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4949 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4950 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4951 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4957 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4958 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4959 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4960 r_refdef.view.frustum[0].dist = m[15] - m[12];
4962 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4963 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4964 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4965 r_refdef.view.frustum[1].dist = m[15] + m[12];
4967 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4968 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4969 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4970 r_refdef.view.frustum[2].dist = m[15] - m[13];
4972 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4973 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4974 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4975 r_refdef.view.frustum[3].dist = m[15] + m[13];
4977 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4978 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4979 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4980 r_refdef.view.frustum[4].dist = m[15] - m[14];
4982 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4983 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4984 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4985 r_refdef.view.frustum[5].dist = m[15] + m[14];
4988 if (r_refdef.view.useperspective)
4990 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4991 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]);
4992 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]);
4993 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]);
4994 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]);
4996 // then the normals from the corners relative to origin
4997 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4998 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4999 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5000 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5002 // in a NORMAL view, forward cross left == up
5003 // in a REFLECTED view, forward cross left == down
5004 // so our cross products above need to be adjusted for a left handed coordinate system
5005 CrossProduct(forward, left, v);
5006 if(DotProduct(v, up) < 0)
5008 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5009 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5010 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5011 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5014 // Leaving those out was a mistake, those were in the old code, and they
5015 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5016 // I couldn't reproduce it after adding those normalizations. --blub
5017 VectorNormalize(r_refdef.view.frustum[0].normal);
5018 VectorNormalize(r_refdef.view.frustum[1].normal);
5019 VectorNormalize(r_refdef.view.frustum[2].normal);
5020 VectorNormalize(r_refdef.view.frustum[3].normal);
5022 // make the corners absolute
5023 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5024 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5025 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5026 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5029 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5031 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5032 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5033 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5034 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5035 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5039 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5040 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5041 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5042 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5043 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5044 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5045 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5046 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5047 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5048 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5050 r_refdef.view.numfrustumplanes = 5;
5052 if (r_refdef.view.useclipplane)
5054 r_refdef.view.numfrustumplanes = 6;
5055 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5058 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5059 PlaneClassify(r_refdef.view.frustum + i);
5061 // LordHavoc: note to all quake engine coders, Quake had a special case
5062 // for 90 degrees which assumed a square view (wrong), so I removed it,
5063 // Quake2 has it disabled as well.
5065 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5066 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5067 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5068 //PlaneClassify(&frustum[0]);
5070 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5071 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5072 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5073 //PlaneClassify(&frustum[1]);
5075 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5076 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5077 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5078 //PlaneClassify(&frustum[2]);
5080 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5081 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5082 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5083 //PlaneClassify(&frustum[3]);
5086 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5087 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5088 //PlaneClassify(&frustum[4]);
5091 void R_View_UpdateWithScissor(const int *myscissor)
5093 R_Main_ResizeViewCache();
5094 R_View_SetFrustum(myscissor);
5095 R_View_WorldVisibility(r_refdef.view.useclipplane);
5096 R_View_UpdateEntityVisible();
5097 R_View_UpdateEntityLighting();
5100 void R_View_Update(void)
5102 R_Main_ResizeViewCache();
5103 R_View_SetFrustum(NULL);
5104 R_View_WorldVisibility(r_refdef.view.useclipplane);
5105 R_View_UpdateEntityVisible();
5106 R_View_UpdateEntityLighting();
5109 void R_SetupView(qboolean allowwaterclippingplane)
5111 const float *customclipplane = NULL;
5113 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5115 // LordHavoc: couldn't figure out how to make this approach the
5116 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5117 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5118 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5119 dist = r_refdef.view.clipplane.dist;
5120 plane[0] = r_refdef.view.clipplane.normal[0];
5121 plane[1] = r_refdef.view.clipplane.normal[1];
5122 plane[2] = r_refdef.view.clipplane.normal[2];
5124 customclipplane = plane;
5127 if (!r_refdef.view.useperspective)
5128 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);
5129 else if (vid.stencil && r_useinfinitefarclip.integer)
5130 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);
5132 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);
5133 R_SetViewport(&r_refdef.view.viewport);
5136 void R_EntityMatrix(const matrix4x4_t *matrix)
5138 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5140 gl_modelmatrixchanged = false;
5141 gl_modelmatrix = *matrix;
5142 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5143 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5144 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5145 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5147 switch(vid.renderpath)
5149 case RENDERPATH_D3D9:
5151 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5152 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5155 case RENDERPATH_D3D10:
5156 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5158 case RENDERPATH_D3D11:
5159 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5161 case RENDERPATH_GL13:
5162 case RENDERPATH_GL11:
5163 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5165 case RENDERPATH_SOFT:
5166 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5167 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5169 case RENDERPATH_GL20:
5170 case RENDERPATH_GLES2:
5171 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5172 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5178 void R_ResetViewRendering2D(void)
5180 r_viewport_t viewport;
5183 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5184 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);
5185 R_SetViewport(&viewport);
5186 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5187 GL_Color(1, 1, 1, 1);
5188 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5189 GL_BlendFunc(GL_ONE, GL_ZERO);
5190 GL_ScissorTest(false);
5191 GL_DepthMask(false);
5192 GL_DepthRange(0, 1);
5193 GL_DepthTest(false);
5194 GL_DepthFunc(GL_LEQUAL);
5195 R_EntityMatrix(&identitymatrix);
5196 R_Mesh_ResetTextureState();
5197 GL_PolygonOffset(0, 0);
5198 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5199 switch(vid.renderpath)
5201 case RENDERPATH_GL11:
5202 case RENDERPATH_GL13:
5203 case RENDERPATH_GL20:
5204 case RENDERPATH_GLES2:
5205 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5207 case RENDERPATH_D3D9:
5208 case RENDERPATH_D3D10:
5209 case RENDERPATH_D3D11:
5210 case RENDERPATH_SOFT:
5213 GL_CullFace(GL_NONE);
5216 void R_ResetViewRendering3D(void)
5221 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5222 GL_Color(1, 1, 1, 1);
5223 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5224 GL_BlendFunc(GL_ONE, GL_ZERO);
5225 GL_ScissorTest(true);
5227 GL_DepthRange(0, 1);
5229 GL_DepthFunc(GL_LEQUAL);
5230 R_EntityMatrix(&identitymatrix);
5231 R_Mesh_ResetTextureState();
5232 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5233 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5234 switch(vid.renderpath)
5236 case RENDERPATH_GL11:
5237 case RENDERPATH_GL13:
5238 case RENDERPATH_GL20:
5239 case RENDERPATH_GLES2:
5240 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5242 case RENDERPATH_D3D9:
5243 case RENDERPATH_D3D10:
5244 case RENDERPATH_D3D11:
5245 case RENDERPATH_SOFT:
5248 GL_CullFace(r_refdef.view.cullface_back);
5253 R_RenderView_UpdateViewVectors
5256 static void R_RenderView_UpdateViewVectors(void)
5258 // break apart the view matrix into vectors for various purposes
5259 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5260 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5261 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5262 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5263 // make an inverted copy of the view matrix for tracking sprites
5264 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5267 void R_RenderScene(void);
5268 void R_RenderWaterPlanes(void);
5270 static void R_Water_StartFrame(void)
5273 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5274 r_waterstate_waterplane_t *p;
5276 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5279 switch(vid.renderpath)
5281 case RENDERPATH_GL20:
5282 case RENDERPATH_D3D9:
5283 case RENDERPATH_D3D10:
5284 case RENDERPATH_D3D11:
5285 case RENDERPATH_SOFT:
5286 case RENDERPATH_GLES2:
5288 case RENDERPATH_GL13:
5289 case RENDERPATH_GL11:
5293 // set waterwidth and waterheight to the water resolution that will be
5294 // used (often less than the screen resolution for faster rendering)
5295 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5296 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5298 // calculate desired texture sizes
5299 // can't use water if the card does not support the texture size
5300 if (!r_water.integer || r_showsurfaces.integer)
5301 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5302 else if (vid.support.arb_texture_non_power_of_two)
5304 texturewidth = waterwidth;
5305 textureheight = waterheight;
5306 camerawidth = waterwidth;
5307 cameraheight = waterheight;
5311 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5312 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5313 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5314 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5317 // allocate textures as needed
5318 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5320 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5321 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5323 if (p->texture_refraction)
5324 R_FreeTexture(p->texture_refraction);
5325 p->texture_refraction = NULL;
5326 if (p->texture_reflection)
5327 R_FreeTexture(p->texture_reflection);
5328 p->texture_reflection = NULL;
5329 if (p->texture_camera)
5330 R_FreeTexture(p->texture_camera);
5331 p->texture_camera = NULL;
5333 memset(&r_waterstate, 0, sizeof(r_waterstate));
5334 r_waterstate.texturewidth = texturewidth;
5335 r_waterstate.textureheight = textureheight;
5336 r_waterstate.camerawidth = camerawidth;
5337 r_waterstate.cameraheight = cameraheight;
5340 if (r_waterstate.texturewidth)
5342 r_waterstate.enabled = true;
5344 // when doing a reduced render (HDR) we want to use a smaller area
5345 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5346 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5348 // set up variables that will be used in shader setup
5349 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5350 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5351 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5352 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5355 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5356 r_waterstate.numwaterplanes = 0;
5359 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5361 int triangleindex, planeindex;
5367 r_waterstate_waterplane_t *p;
5368 texture_t *t = R_GetCurrentTexture(surface->texture);
5370 // just use the first triangle with a valid normal for any decisions
5371 VectorClear(normal);
5372 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5374 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5375 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5376 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5377 TriangleNormal(vert[0], vert[1], vert[2], normal);
5378 if (VectorLength2(normal) >= 0.001)
5382 VectorCopy(normal, plane.normal);
5383 VectorNormalize(plane.normal);
5384 plane.dist = DotProduct(vert[0], plane.normal);
5385 PlaneClassify(&plane);
5386 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5388 // skip backfaces (except if nocullface is set)
5389 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5391 VectorNegate(plane.normal, plane.normal);
5393 PlaneClassify(&plane);
5397 // find a matching plane if there is one
5398 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5399 if(p->camera_entity == t->camera_entity)
5400 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5402 if (planeindex >= r_waterstate.maxwaterplanes)
5403 return; // nothing we can do, out of planes
5405 // if this triangle does not fit any known plane rendered this frame, add one
5406 if (planeindex >= r_waterstate.numwaterplanes)
5408 // store the new plane
5409 r_waterstate.numwaterplanes++;
5411 // clear materialflags and pvs
5412 p->materialflags = 0;
5413 p->pvsvalid = false;
5414 p->camera_entity = t->camera_entity;
5415 VectorCopy(surface->mins, p->mins);
5416 VectorCopy(surface->maxs, p->maxs);
5421 p->mins[0] = min(p->mins[0], surface->mins[0]);
5422 p->mins[1] = min(p->mins[1], surface->mins[1]);
5423 p->mins[2] = min(p->mins[2], surface->mins[2]);
5424 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5425 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5426 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5428 // merge this surface's materialflags into the waterplane
5429 p->materialflags |= t->currentmaterialflags;
5430 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5432 // merge this surface's PVS into the waterplane
5433 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5434 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5435 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5437 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5443 static void R_Water_ProcessPlanes(void)
5446 r_refdef_view_t originalview;
5447 r_refdef_view_t myview;
5449 r_waterstate_waterplane_t *p;
5452 originalview = r_refdef.view;
5454 // make sure enough textures are allocated
5455 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5457 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5459 if (!p->texture_refraction)
5460 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);
5461 if (!p->texture_refraction)
5464 else if (p->materialflags & MATERIALFLAG_CAMERA)
5466 if (!p->texture_camera)
5467 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);
5468 if (!p->texture_camera)
5472 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5474 if (!p->texture_reflection)
5475 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);
5476 if (!p->texture_reflection)
5482 r_refdef.view = originalview;
5483 r_refdef.view.showdebug = false;
5484 r_refdef.view.width = r_waterstate.waterwidth;
5485 r_refdef.view.height = r_waterstate.waterheight;
5486 r_refdef.view.useclipplane = true;
5487 myview = r_refdef.view;
5488 r_waterstate.renderingscene = true;
5489 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5491 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5493 r_refdef.view = myview;
5494 if(r_water_scissormode.integer)
5497 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5498 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5501 // render reflected scene and copy into texture
5502 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5503 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5504 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5505 r_refdef.view.clipplane = p->plane;
5507 // reverse the cullface settings for this render
5508 r_refdef.view.cullface_front = GL_FRONT;
5509 r_refdef.view.cullface_back = GL_BACK;
5510 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5512 r_refdef.view.usecustompvs = true;
5514 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5516 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5519 R_ResetViewRendering3D();
5520 R_ClearScreen(r_refdef.fogenabled);
5521 if(r_water_scissormode.integer & 2)
5522 R_View_UpdateWithScissor(myscissor);
5525 if(r_water_scissormode.integer & 1)
5526 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5529 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);
5532 // render the normal view scene and copy into texture
5533 // (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)
5534 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5536 r_refdef.view = myview;
5537 if(r_water_scissormode.integer)
5540 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5541 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5544 r_waterstate.renderingrefraction = true;
5546 r_refdef.view.clipplane = p->plane;
5547 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5548 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5550 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5552 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5553 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5554 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5555 R_RenderView_UpdateViewVectors();
5556 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5558 r_refdef.view.usecustompvs = true;
5559 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);
5563 PlaneClassify(&r_refdef.view.clipplane);
5565 R_ResetViewRendering3D();
5566 R_ClearScreen(r_refdef.fogenabled);
5567 if(r_water_scissormode.integer & 2)
5568 R_View_UpdateWithScissor(myscissor);
5571 if(r_water_scissormode.integer & 1)
5572 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5575 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);
5576 r_waterstate.renderingrefraction = false;
5578 else if (p->materialflags & MATERIALFLAG_CAMERA)
5580 r_refdef.view = myview;
5582 r_refdef.view.clipplane = p->plane;
5583 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5584 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5586 r_refdef.view.width = r_waterstate.camerawidth;
5587 r_refdef.view.height = r_waterstate.cameraheight;
5588 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5589 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5591 if(p->camera_entity)
5593 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5594 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5597 // note: all of the view is used for displaying... so
5598 // there is no use in scissoring
5600 // reverse the cullface settings for this render
5601 r_refdef.view.cullface_front = GL_FRONT;
5602 r_refdef.view.cullface_back = GL_BACK;
5603 // also reverse the view matrix
5604 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
5605 R_RenderView_UpdateViewVectors();
5606 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5608 r_refdef.view.usecustompvs = true;
5609 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);
5612 // camera needs no clipplane
5613 r_refdef.view.useclipplane = false;
5615 PlaneClassify(&r_refdef.view.clipplane);
5617 R_ResetViewRendering3D();
5618 R_ClearScreen(r_refdef.fogenabled);
5622 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);
5623 r_waterstate.renderingrefraction = false;
5627 r_waterstate.renderingscene = false;
5628 r_refdef.view = originalview;
5629 R_ResetViewRendering3D();
5630 R_ClearScreen(r_refdef.fogenabled);
5634 r_refdef.view = originalview;
5635 r_waterstate.renderingscene = false;
5636 Cvar_SetValueQuick(&r_water, 0);
5637 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5641 void R_Bloom_StartFrame(void)
5643 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5645 switch(vid.renderpath)
5647 case RENDERPATH_GL20:
5648 case RENDERPATH_D3D9:
5649 case RENDERPATH_D3D10:
5650 case RENDERPATH_D3D11:
5651 case RENDERPATH_SOFT:
5652 case RENDERPATH_GLES2:
5654 case RENDERPATH_GL13:
5655 case RENDERPATH_GL11:
5659 // set bloomwidth and bloomheight to the bloom resolution that will be
5660 // used (often less than the screen resolution for faster rendering)
5661 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5662 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5663 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5664 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5665 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5667 // calculate desired texture sizes
5668 if (vid.support.arb_texture_non_power_of_two)
5670 screentexturewidth = r_refdef.view.width;
5671 screentextureheight = r_refdef.view.height;
5672 bloomtexturewidth = r_bloomstate.bloomwidth;
5673 bloomtextureheight = r_bloomstate.bloomheight;
5677 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5678 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5679 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5680 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5683 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))
5685 Cvar_SetValueQuick(&r_hdr, 0);
5686 Cvar_SetValueQuick(&r_bloom, 0);
5687 Cvar_SetValueQuick(&r_motionblur, 0);
5688 Cvar_SetValueQuick(&r_damageblur, 0);
5691 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)))
5692 screentexturewidth = screentextureheight = 0;
5693 if (!r_hdr.integer && !r_bloom.integer)
5694 bloomtexturewidth = bloomtextureheight = 0;
5696 // allocate textures as needed
5697 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5699 if (r_bloomstate.texture_screen)
5700 R_FreeTexture(r_bloomstate.texture_screen);
5701 r_bloomstate.texture_screen = NULL;
5702 r_bloomstate.screentexturewidth = screentexturewidth;
5703 r_bloomstate.screentextureheight = screentextureheight;
5704 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5705 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);
5707 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5709 if (r_bloomstate.texture_bloom)
5710 R_FreeTexture(r_bloomstate.texture_bloom);
5711 r_bloomstate.texture_bloom = NULL;
5712 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5713 r_bloomstate.bloomtextureheight = bloomtextureheight;
5714 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5715 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);
5718 // when doing a reduced render (HDR) we want to use a smaller area
5719 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5720 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5721 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5722 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5723 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5725 // set up a texcoord array for the full resolution screen image
5726 // (we have to keep this around to copy back during final render)
5727 r_bloomstate.screentexcoord2f[0] = 0;
5728 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5729 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5730 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5731 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5732 r_bloomstate.screentexcoord2f[5] = 0;
5733 r_bloomstate.screentexcoord2f[6] = 0;
5734 r_bloomstate.screentexcoord2f[7] = 0;
5736 // set up a texcoord array for the reduced resolution bloom image
5737 // (which will be additive blended over the screen image)
5738 r_bloomstate.bloomtexcoord2f[0] = 0;
5739 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5740 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5741 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5742 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5743 r_bloomstate.bloomtexcoord2f[5] = 0;
5744 r_bloomstate.bloomtexcoord2f[6] = 0;
5745 r_bloomstate.bloomtexcoord2f[7] = 0;
5747 switch(vid.renderpath)
5749 case RENDERPATH_GL11:
5750 case RENDERPATH_GL13:
5751 case RENDERPATH_GL20:
5752 case RENDERPATH_SOFT:
5753 case RENDERPATH_GLES2:
5755 case RENDERPATH_D3D9:
5756 case RENDERPATH_D3D10:
5757 case RENDERPATH_D3D11:
5760 for (i = 0;i < 4;i++)
5762 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5763 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5764 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5765 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5771 if (r_hdr.integer || r_bloom.integer)
5773 r_bloomstate.enabled = true;
5774 r_bloomstate.hdr = r_hdr.integer != 0;
5777 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);
5780 void R_Bloom_CopyBloomTexture(float colorscale)
5782 r_refdef.stats.bloom++;
5784 // scale down screen texture to the bloom texture size
5786 R_SetViewport(&r_bloomstate.viewport);
5787 GL_BlendFunc(GL_ONE, GL_ZERO);
5788 GL_Color(colorscale, colorscale, colorscale, 1);
5789 // 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...
5790 switch(vid.renderpath)
5792 case RENDERPATH_GL11:
5793 case RENDERPATH_GL13:
5794 case RENDERPATH_GL20:
5795 case RENDERPATH_SOFT:
5796 case RENDERPATH_GLES2:
5797 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5799 case RENDERPATH_D3D9:
5800 case RENDERPATH_D3D10:
5801 case RENDERPATH_D3D11:
5802 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5805 // TODO: do boxfilter scale-down in shader?
5806 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5807 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5808 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5810 // we now have a bloom image in the framebuffer
5811 // copy it into the bloom image texture for later processing
5812 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);
5813 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5816 void R_Bloom_CopyHDRTexture(void)
5818 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);
5819 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5822 void R_Bloom_MakeTexture(void)
5825 float xoffset, yoffset, r, brighten;
5827 r_refdef.stats.bloom++;
5829 R_ResetViewRendering2D();
5831 // we have a bloom image in the framebuffer
5833 R_SetViewport(&r_bloomstate.viewport);
5835 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5838 r = bound(0, r_bloom_colorexponent.value / x, 1);
5839 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5841 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5842 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5843 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5844 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5846 // copy the vertically blurred bloom view to a texture
5847 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);
5848 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5851 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5852 brighten = r_bloom_brighten.value;
5854 brighten *= r_hdr_range.value;
5855 brighten = sqrt(brighten);
5857 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5858 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5860 for (dir = 0;dir < 2;dir++)
5862 // blend on at multiple vertical offsets to achieve a vertical blur
5863 // TODO: do offset blends using GLSL
5864 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5865 GL_BlendFunc(GL_ONE, GL_ZERO);
5866 for (x = -range;x <= range;x++)
5868 if (!dir){xoffset = 0;yoffset = x;}
5869 else {xoffset = x;yoffset = 0;}
5870 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5871 yoffset /= (float)r_bloomstate.bloomtextureheight;
5872 // compute a texcoord array with the specified x and y offset
5873 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5874 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5875 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5876 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5877 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5878 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5879 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5880 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5881 // this r value looks like a 'dot' particle, fading sharply to
5882 // black at the edges
5883 // (probably not realistic but looks good enough)
5884 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5885 //r = brighten/(range*2+1);
5886 r = brighten / (range * 2 + 1);
5888 r *= (1 - x*x/(float)(range*range));
5889 GL_Color(r, r, r, 1);
5890 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5891 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5892 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5893 GL_BlendFunc(GL_ONE, GL_ONE);
5896 // copy the vertically blurred bloom view to a texture
5897 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);
5898 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5902 void R_HDR_RenderBloomTexture(void)
5904 int oldwidth, oldheight;
5905 float oldcolorscale;
5906 qboolean oldwaterstate;
5908 oldwaterstate = r_waterstate.enabled;
5909 oldcolorscale = r_refdef.view.colorscale;
5910 oldwidth = r_refdef.view.width;
5911 oldheight = r_refdef.view.height;
5912 r_refdef.view.width = r_bloomstate.bloomwidth;
5913 r_refdef.view.height = r_bloomstate.bloomheight;
5915 if(r_hdr.integer < 2)
5916 r_waterstate.enabled = false;
5918 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5919 // TODO: add exposure compensation features
5920 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5922 r_refdef.view.showdebug = false;
5923 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5925 R_ResetViewRendering3D();
5927 R_ClearScreen(r_refdef.fogenabled);
5928 if (r_timereport_active)
5929 R_TimeReport("HDRclear");
5932 if (r_timereport_active)
5933 R_TimeReport("visibility");
5935 // only do secondary renders with HDR if r_hdr is 2 or higher
5936 r_waterstate.numwaterplanes = 0;
5937 if (r_waterstate.enabled)
5938 R_RenderWaterPlanes();
5940 r_refdef.view.showdebug = true;
5942 r_waterstate.numwaterplanes = 0;
5944 R_ResetViewRendering2D();
5946 R_Bloom_CopyHDRTexture();
5947 R_Bloom_MakeTexture();
5949 // restore the view settings
5950 r_waterstate.enabled = oldwaterstate;
5951 r_refdef.view.width = oldwidth;
5952 r_refdef.view.height = oldheight;
5953 r_refdef.view.colorscale = oldcolorscale;
5955 R_ResetViewRendering3D();
5957 R_ClearScreen(r_refdef.fogenabled);
5958 if (r_timereport_active)
5959 R_TimeReport("viewclear");
5962 static void R_BlendView(void)
5964 unsigned int permutation;
5965 float uservecs[4][4];
5967 switch (vid.renderpath)
5969 case RENDERPATH_GL20:
5970 case RENDERPATH_D3D9:
5971 case RENDERPATH_D3D10:
5972 case RENDERPATH_D3D11:
5973 case RENDERPATH_SOFT:
5974 case RENDERPATH_GLES2:
5976 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5977 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5978 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5979 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5980 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5982 if (r_bloomstate.texture_screen)
5984 // make sure the buffer is available
5985 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5987 R_ResetViewRendering2D();
5989 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5991 // declare variables
5993 static float avgspeed;
5995 speed = VectorLength(cl.movement_velocity);
5997 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5998 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6000 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6001 speed = bound(0, speed, 1);
6002 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6004 // calculate values into a standard alpha
6005 cl.motionbluralpha = 1 - exp(-
6007 (r_motionblur.value * speed / 80)
6009 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6012 max(0.0001, cl.time - cl.oldtime) // fps independent
6015 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6016 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6018 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6020 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6021 GL_Color(1, 1, 1, cl.motionbluralpha);
6022 switch(vid.renderpath)
6024 case RENDERPATH_GL11:
6025 case RENDERPATH_GL13:
6026 case RENDERPATH_GL20:
6027 case RENDERPATH_SOFT:
6028 case RENDERPATH_GLES2:
6029 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6031 case RENDERPATH_D3D9:
6032 case RENDERPATH_D3D10:
6033 case RENDERPATH_D3D11:
6034 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6037 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6038 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6039 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6043 // copy view into the screen texture
6044 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);
6045 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6047 else if (!r_bloomstate.texture_bloom)
6049 // we may still have to do view tint...
6050 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6052 // apply a color tint to the whole view
6053 R_ResetViewRendering2D();
6054 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6055 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6056 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6057 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6058 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6060 break; // no screen processing, no bloom, skip it
6063 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6065 // render simple bloom effect
6066 // copy the screen and shrink it and darken it for the bloom process
6067 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6068 // make the bloom texture
6069 R_Bloom_MakeTexture();
6072 #if _MSC_VER >= 1400
6073 #define sscanf sscanf_s
6075 memset(uservecs, 0, sizeof(uservecs));
6076 if (r_glsl_postprocess_uservec1_enable.integer)
6077 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6078 if (r_glsl_postprocess_uservec2_enable.integer)
6079 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6080 if (r_glsl_postprocess_uservec3_enable.integer)
6081 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6082 if (r_glsl_postprocess_uservec4_enable.integer)
6083 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6085 R_ResetViewRendering2D();
6086 GL_Color(1, 1, 1, 1);
6087 GL_BlendFunc(GL_ONE, GL_ZERO);
6089 switch(vid.renderpath)
6091 case RENDERPATH_GL20:
6092 case RENDERPATH_GLES2:
6093 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6094 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6095 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6096 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6097 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6098 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]);
6099 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6100 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]);
6101 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]);
6102 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]);
6103 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]);
6104 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6105 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6106 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);
6108 case RENDERPATH_D3D9:
6110 // 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...
6111 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6112 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6113 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6114 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6115 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6116 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6117 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6118 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6119 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6120 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6121 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6122 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6123 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6124 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6127 case RENDERPATH_D3D10:
6128 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6130 case RENDERPATH_D3D11:
6131 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6133 case RENDERPATH_SOFT:
6134 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6135 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6136 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6137 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6138 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6139 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6140 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6141 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6142 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6143 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6144 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6145 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6146 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6147 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6152 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6153 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6155 case RENDERPATH_GL13:
6156 case RENDERPATH_GL11:
6157 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6159 // apply a color tint to the whole view
6160 R_ResetViewRendering2D();
6161 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6162 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6163 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6164 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6165 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6171 matrix4x4_t r_waterscrollmatrix;
6173 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6175 if (r_refdef.fog_density)
6177 r_refdef.fogcolor[0] = r_refdef.fog_red;
6178 r_refdef.fogcolor[1] = r_refdef.fog_green;
6179 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6181 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6182 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6183 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6184 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6188 VectorCopy(r_refdef.fogcolor, fogvec);
6189 // color.rgb *= ContrastBoost * SceneBrightness;
6190 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6191 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6192 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6193 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6198 void R_UpdateVariables(void)
6202 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6204 r_refdef.farclip = r_farclip_base.value;
6205 if (r_refdef.scene.worldmodel)
6206 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6207 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6209 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6210 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6211 r_refdef.polygonfactor = 0;
6212 r_refdef.polygonoffset = 0;
6213 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6214 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6216 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6217 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6218 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6219 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6220 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6221 if (FAKELIGHT_ENABLED)
6223 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6225 if (r_showsurfaces.integer)
6227 r_refdef.scene.rtworld = false;
6228 r_refdef.scene.rtworldshadows = false;
6229 r_refdef.scene.rtdlight = false;
6230 r_refdef.scene.rtdlightshadows = false;
6231 r_refdef.lightmapintensity = 0;
6234 if (gamemode == GAME_NEHAHRA)
6236 if (gl_fogenable.integer)
6238 r_refdef.oldgl_fogenable = true;
6239 r_refdef.fog_density = gl_fogdensity.value;
6240 r_refdef.fog_red = gl_fogred.value;
6241 r_refdef.fog_green = gl_foggreen.value;
6242 r_refdef.fog_blue = gl_fogblue.value;
6243 r_refdef.fog_alpha = 1;
6244 r_refdef.fog_start = 0;
6245 r_refdef.fog_end = gl_skyclip.value;
6246 r_refdef.fog_height = 1<<30;
6247 r_refdef.fog_fadedepth = 128;
6249 else if (r_refdef.oldgl_fogenable)
6251 r_refdef.oldgl_fogenable = false;
6252 r_refdef.fog_density = 0;
6253 r_refdef.fog_red = 0;
6254 r_refdef.fog_green = 0;
6255 r_refdef.fog_blue = 0;
6256 r_refdef.fog_alpha = 0;
6257 r_refdef.fog_start = 0;
6258 r_refdef.fog_end = 0;
6259 r_refdef.fog_height = 1<<30;
6260 r_refdef.fog_fadedepth = 128;
6264 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6265 r_refdef.fog_start = max(0, r_refdef.fog_start);
6266 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6268 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6270 if (r_refdef.fog_density && r_drawfog.integer)
6272 r_refdef.fogenabled = true;
6273 // this is the point where the fog reaches 0.9986 alpha, which we
6274 // consider a good enough cutoff point for the texture
6275 // (0.9986 * 256 == 255.6)
6276 if (r_fog_exp2.integer)
6277 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6279 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6280 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6281 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6282 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6283 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6284 R_BuildFogHeightTexture();
6285 // fog color was already set
6286 // update the fog texture
6287 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)
6288 R_BuildFogTexture();
6289 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6290 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6293 r_refdef.fogenabled = false;
6295 switch(vid.renderpath)
6297 case RENDERPATH_GL20:
6298 case RENDERPATH_D3D9:
6299 case RENDERPATH_D3D10:
6300 case RENDERPATH_D3D11:
6301 case RENDERPATH_SOFT:
6302 case RENDERPATH_GLES2:
6303 if(v_glslgamma.integer && !vid_gammatables_trivial)
6305 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6307 // build GLSL gamma texture
6308 #define RAMPWIDTH 256
6309 unsigned short ramp[RAMPWIDTH * 3];
6310 unsigned char rampbgr[RAMPWIDTH][4];
6313 r_texture_gammaramps_serial = vid_gammatables_serial;
6315 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6316 for(i = 0; i < RAMPWIDTH; ++i)
6318 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6319 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6320 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6323 if (r_texture_gammaramps)
6325 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6329 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6335 // remove GLSL gamma texture
6338 case RENDERPATH_GL13:
6339 case RENDERPATH_GL11:
6344 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6345 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6351 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6352 if( scenetype != r_currentscenetype ) {
6353 // store the old scenetype
6354 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6355 r_currentscenetype = scenetype;
6356 // move in the new scene
6357 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6366 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6368 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6369 if( scenetype == r_currentscenetype ) {
6370 return &r_refdef.scene;
6372 return &r_scenes_store[ scenetype ];
6381 int dpsoftrast_test;
6382 void R_RenderView(void)
6384 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6386 dpsoftrast_test = r_test.integer;
6388 if (r_timereport_active)
6389 R_TimeReport("start");
6390 r_textureframe++; // used only by R_GetCurrentTexture
6391 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6393 if(R_CompileShader_CheckStaticParms())
6396 if (!r_drawentities.integer)
6397 r_refdef.scene.numentities = 0;
6399 R_AnimCache_ClearCache();
6400 R_FrameData_NewFrame();
6402 /* adjust for stereo display */
6403 if(R_Stereo_Active())
6405 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);
6406 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6409 if (r_refdef.view.isoverlay)
6411 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6412 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6413 R_TimeReport("depthclear");
6415 r_refdef.view.showdebug = false;
6417 r_waterstate.enabled = false;
6418 r_waterstate.numwaterplanes = 0;
6422 r_refdef.view.matrix = originalmatrix;
6428 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6430 r_refdef.view.matrix = originalmatrix;
6431 return; //Host_Error ("R_RenderView: NULL worldmodel");
6434 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6436 R_RenderView_UpdateViewVectors();
6438 R_Shadow_UpdateWorldLightSelection();
6440 R_Bloom_StartFrame();
6441 R_Water_StartFrame();
6444 if (r_timereport_active)
6445 R_TimeReport("viewsetup");
6447 R_ResetViewRendering3D();
6449 if (r_refdef.view.clear || r_refdef.fogenabled)
6451 R_ClearScreen(r_refdef.fogenabled);
6452 if (r_timereport_active)
6453 R_TimeReport("viewclear");
6455 r_refdef.view.clear = true;
6457 // this produces a bloom texture to be used in R_BlendView() later
6458 if (r_hdr.integer && r_bloomstate.bloomwidth)
6460 R_HDR_RenderBloomTexture();
6461 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6462 r_textureframe++; // used only by R_GetCurrentTexture
6465 r_refdef.view.showdebug = true;
6468 if (r_timereport_active)
6469 R_TimeReport("visibility");
6471 r_waterstate.numwaterplanes = 0;
6472 if (r_waterstate.enabled)
6473 R_RenderWaterPlanes();
6476 r_waterstate.numwaterplanes = 0;
6479 if (r_timereport_active)
6480 R_TimeReport("blendview");
6482 GL_Scissor(0, 0, vid.width, vid.height);
6483 GL_ScissorTest(false);
6485 r_refdef.view.matrix = originalmatrix;
6490 void R_RenderWaterPlanes(void)
6492 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6494 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6495 if (r_timereport_active)
6496 R_TimeReport("waterworld");
6499 // don't let sound skip if going slow
6500 if (r_refdef.scene.extraupdate)
6503 R_DrawModelsAddWaterPlanes();
6504 if (r_timereport_active)
6505 R_TimeReport("watermodels");
6507 if (r_waterstate.numwaterplanes)
6509 R_Water_ProcessPlanes();
6510 if (r_timereport_active)
6511 R_TimeReport("waterscenes");
6515 extern void R_DrawLightningBeams (void);
6516 extern void VM_CL_AddPolygonsToMeshQueue (void);
6517 extern void R_DrawPortals (void);
6518 extern cvar_t cl_locs_show;
6519 static void R_DrawLocs(void);
6520 static void R_DrawEntityBBoxes(void);
6521 static void R_DrawModelDecals(void);
6522 extern void R_DrawModelShadows(void);
6523 extern void R_DrawModelShadowMaps(void);
6524 extern cvar_t cl_decals_newsystem;
6525 extern qboolean r_shadow_usingdeferredprepass;
6526 void R_RenderScene(void)
6528 qboolean shadowmapping = false;
6530 if (r_timereport_active)
6531 R_TimeReport("beginscene");
6533 r_refdef.stats.renders++;
6537 // don't let sound skip if going slow
6538 if (r_refdef.scene.extraupdate)
6541 R_MeshQueue_BeginScene();
6545 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);
6547 if (r_timereport_active)
6548 R_TimeReport("skystartframe");
6550 if (cl.csqc_vidvars.drawworld)
6552 // don't let sound skip if going slow
6553 if (r_refdef.scene.extraupdate)
6556 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6558 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6559 if (r_timereport_active)
6560 R_TimeReport("worldsky");
6563 if (R_DrawBrushModelsSky() && r_timereport_active)
6564 R_TimeReport("bmodelsky");
6566 if (skyrendermasked && skyrenderlater)
6568 // we have to force off the water clipping plane while rendering sky
6572 if (r_timereport_active)
6573 R_TimeReport("sky");
6577 R_AnimCache_CacheVisibleEntities();
6578 if (r_timereport_active)
6579 R_TimeReport("animation");
6581 R_Shadow_PrepareLights();
6582 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6583 R_Shadow_PrepareModelShadows();
6584 if (r_timereport_active)
6585 R_TimeReport("preparelights");
6587 if (R_Shadow_ShadowMappingEnabled())
6588 shadowmapping = true;
6590 if (r_shadow_usingdeferredprepass)
6591 R_Shadow_DrawPrepass();
6593 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6595 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6596 if (r_timereport_active)
6597 R_TimeReport("worlddepth");
6599 if (r_depthfirst.integer >= 2)
6601 R_DrawModelsDepth();
6602 if (r_timereport_active)
6603 R_TimeReport("modeldepth");
6606 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6608 R_DrawModelShadowMaps();
6609 R_ResetViewRendering3D();
6610 // don't let sound skip if going slow
6611 if (r_refdef.scene.extraupdate)
6615 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6617 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6618 if (r_timereport_active)
6619 R_TimeReport("world");
6622 // don't let sound skip if going slow
6623 if (r_refdef.scene.extraupdate)
6627 if (r_timereport_active)
6628 R_TimeReport("models");
6630 // don't let sound skip if going slow
6631 if (r_refdef.scene.extraupdate)
6634 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6636 R_DrawModelShadows();
6637 R_ResetViewRendering3D();
6638 // don't let sound skip if going slow
6639 if (r_refdef.scene.extraupdate)
6643 if (!r_shadow_usingdeferredprepass)
6645 R_Shadow_DrawLights();
6646 if (r_timereport_active)
6647 R_TimeReport("rtlights");
6650 // don't let sound skip if going slow
6651 if (r_refdef.scene.extraupdate)
6654 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6656 R_DrawModelShadows();
6657 R_ResetViewRendering3D();
6658 // don't let sound skip if going slow
6659 if (r_refdef.scene.extraupdate)
6663 if (cl.csqc_vidvars.drawworld)
6665 if (cl_decals_newsystem.integer)
6667 R_DrawModelDecals();
6668 if (r_timereport_active)
6669 R_TimeReport("modeldecals");
6674 if (r_timereport_active)
6675 R_TimeReport("decals");
6679 if (r_timereport_active)
6680 R_TimeReport("particles");
6683 if (r_timereport_active)
6684 R_TimeReport("explosions");
6686 R_DrawLightningBeams();
6687 if (r_timereport_active)
6688 R_TimeReport("lightning");
6691 VM_CL_AddPolygonsToMeshQueue();
6693 if (r_refdef.view.showdebug)
6695 if (cl_locs_show.integer)
6698 if (r_timereport_active)
6699 R_TimeReport("showlocs");
6702 if (r_drawportals.integer)
6705 if (r_timereport_active)
6706 R_TimeReport("portals");
6709 if (r_showbboxes.value > 0)
6711 R_DrawEntityBBoxes();
6712 if (r_timereport_active)
6713 R_TimeReport("bboxes");
6717 R_MeshQueue_RenderTransparent();
6718 if (r_timereport_active)
6719 R_TimeReport("drawtrans");
6721 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))
6723 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6724 if (r_timereport_active)
6725 R_TimeReport("worlddebug");
6726 R_DrawModelsDebug();
6727 if (r_timereport_active)
6728 R_TimeReport("modeldebug");
6731 if (cl.csqc_vidvars.drawworld)
6733 R_Shadow_DrawCoronas();
6734 if (r_timereport_active)
6735 R_TimeReport("coronas");
6740 GL_DepthTest(false);
6741 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6742 GL_Color(1, 1, 1, 1);
6743 qglBegin(GL_POLYGON);
6744 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6745 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6746 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6747 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6749 qglBegin(GL_POLYGON);
6750 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]);
6751 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]);
6752 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]);
6753 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]);
6755 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6759 // don't let sound skip if going slow
6760 if (r_refdef.scene.extraupdate)
6763 R_ResetViewRendering2D();
6766 static const unsigned short bboxelements[36] =
6776 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6779 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6781 RSurf_ActiveWorldEntity();
6783 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6784 GL_DepthMask(false);
6785 GL_DepthRange(0, 1);
6786 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6787 // R_Mesh_ResetTextureState();
6789 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6790 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6791 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6792 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6793 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6794 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6795 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6796 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6797 R_FillColors(color4f, 8, cr, cg, cb, ca);
6798 if (r_refdef.fogenabled)
6800 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6802 f1 = RSurf_FogVertex(v);
6804 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6805 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6806 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6809 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6810 R_Mesh_ResetTextureState();
6811 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6812 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6815 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6819 prvm_edict_t *edict;
6820 prvm_prog_t *prog_save = prog;
6822 // this function draws bounding boxes of server entities
6826 GL_CullFace(GL_NONE);
6827 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6831 for (i = 0;i < numsurfaces;i++)
6833 edict = PRVM_EDICT_NUM(surfacelist[i]);
6834 switch ((int)edict->fields.server->solid)
6836 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6837 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6838 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6839 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6840 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6841 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6843 color[3] *= r_showbboxes.value;
6844 color[3] = bound(0, color[3], 1);
6845 GL_DepthTest(!r_showdisabledepthtest.integer);
6846 GL_CullFace(r_refdef.view.cullface_front);
6847 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6853 static void R_DrawEntityBBoxes(void)
6856 prvm_edict_t *edict;
6858 prvm_prog_t *prog_save = prog;
6860 // this function draws bounding boxes of server entities
6866 for (i = 0;i < prog->num_edicts;i++)
6868 edict = PRVM_EDICT_NUM(i);
6869 if (edict->priv.server->free)
6871 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6872 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6874 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6876 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6877 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6883 static const int nomodelelement3i[24] =
6895 static const unsigned short nomodelelement3s[24] =
6907 static const float nomodelvertex3f[6*3] =
6917 static const float nomodelcolor4f[6*4] =
6919 0.0f, 0.0f, 0.5f, 1.0f,
6920 0.0f, 0.0f, 0.5f, 1.0f,
6921 0.0f, 0.5f, 0.0f, 1.0f,
6922 0.0f, 0.5f, 0.0f, 1.0f,
6923 0.5f, 0.0f, 0.0f, 1.0f,
6924 0.5f, 0.0f, 0.0f, 1.0f
6927 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6933 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);
6935 // this is only called once per entity so numsurfaces is always 1, and
6936 // surfacelist is always {0}, so this code does not handle batches
6938 if (rsurface.ent_flags & RENDER_ADDITIVE)
6940 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6941 GL_DepthMask(false);
6943 else if (rsurface.colormod[3] < 1)
6945 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6946 GL_DepthMask(false);
6950 GL_BlendFunc(GL_ONE, GL_ZERO);
6953 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6954 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6955 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6956 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6957 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6958 for (i = 0, c = color4f;i < 6;i++, c += 4)
6960 c[0] *= rsurface.colormod[0];
6961 c[1] *= rsurface.colormod[1];
6962 c[2] *= rsurface.colormod[2];
6963 c[3] *= rsurface.colormod[3];
6965 if (r_refdef.fogenabled)
6967 for (i = 0, c = color4f;i < 6;i++, c += 4)
6969 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6971 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6972 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6973 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6976 // R_Mesh_ResetTextureState();
6977 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6978 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6979 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6982 void R_DrawNoModel(entity_render_t *ent)
6985 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6986 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6987 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6989 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6992 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6994 vec3_t right1, right2, diff, normal;
6996 VectorSubtract (org2, org1, normal);
6998 // calculate 'right' vector for start
6999 VectorSubtract (r_refdef.view.origin, org1, diff);
7000 CrossProduct (normal, diff, right1);
7001 VectorNormalize (right1);
7003 // calculate 'right' vector for end
7004 VectorSubtract (r_refdef.view.origin, org2, diff);
7005 CrossProduct (normal, diff, right2);
7006 VectorNormalize (right2);
7008 vert[ 0] = org1[0] + width * right1[0];
7009 vert[ 1] = org1[1] + width * right1[1];
7010 vert[ 2] = org1[2] + width * right1[2];
7011 vert[ 3] = org1[0] - width * right1[0];
7012 vert[ 4] = org1[1] - width * right1[1];
7013 vert[ 5] = org1[2] - width * right1[2];
7014 vert[ 6] = org2[0] - width * right2[0];
7015 vert[ 7] = org2[1] - width * right2[1];
7016 vert[ 8] = org2[2] - width * right2[2];
7017 vert[ 9] = org2[0] + width * right2[0];
7018 vert[10] = org2[1] + width * right2[1];
7019 vert[11] = org2[2] + width * right2[2];
7022 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)
7024 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7025 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7026 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7027 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7028 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7029 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7030 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7031 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7032 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7033 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7034 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7035 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7038 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7043 VectorSet(v, x, y, z);
7044 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7045 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7047 if (i == mesh->numvertices)
7049 if (mesh->numvertices < mesh->maxvertices)
7051 VectorCopy(v, vertex3f);
7052 mesh->numvertices++;
7054 return mesh->numvertices;
7060 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7064 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7065 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7066 e = mesh->element3i + mesh->numtriangles * 3;
7067 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7069 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7070 if (mesh->numtriangles < mesh->maxtriangles)
7075 mesh->numtriangles++;
7077 element[1] = element[2];
7081 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7085 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7086 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7087 e = mesh->element3i + mesh->numtriangles * 3;
7088 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7090 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7091 if (mesh->numtriangles < mesh->maxtriangles)
7096 mesh->numtriangles++;
7098 element[1] = element[2];
7102 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7103 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7105 int planenum, planenum2;
7108 mplane_t *plane, *plane2;
7110 double temppoints[2][256*3];
7111 // figure out how large a bounding box we need to properly compute this brush
7113 for (w = 0;w < numplanes;w++)
7114 maxdist = max(maxdist, fabs(planes[w].dist));
7115 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7116 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7117 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7121 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7122 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7124 if (planenum2 == planenum)
7126 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);
7129 if (tempnumpoints < 3)
7131 // generate elements forming a triangle fan for this polygon
7132 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7136 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)
7138 texturelayer_t *layer;
7139 layer = t->currentlayers + t->currentnumlayers++;
7141 layer->depthmask = depthmask;
7142 layer->blendfunc1 = blendfunc1;
7143 layer->blendfunc2 = blendfunc2;
7144 layer->texture = texture;
7145 layer->texmatrix = *matrix;
7146 layer->color[0] = r;
7147 layer->color[1] = g;
7148 layer->color[2] = b;
7149 layer->color[3] = a;
7152 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7154 if(parms[0] == 0 && parms[1] == 0)
7156 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7157 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7162 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7165 index = parms[2] + r_refdef.scene.time * parms[3];
7166 index -= floor(index);
7167 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7170 case Q3WAVEFUNC_NONE:
7171 case Q3WAVEFUNC_NOISE:
7172 case Q3WAVEFUNC_COUNT:
7175 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7176 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7177 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7178 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7179 case Q3WAVEFUNC_TRIANGLE:
7181 f = index - floor(index);
7192 f = parms[0] + parms[1] * f;
7193 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7194 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7198 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7203 matrix4x4_t matrix, temp;
7204 switch(tcmod->tcmod)
7208 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7209 matrix = r_waterscrollmatrix;
7211 matrix = identitymatrix;
7213 case Q3TCMOD_ENTITYTRANSLATE:
7214 // this is used in Q3 to allow the gamecode to control texcoord
7215 // scrolling on the entity, which is not supported in darkplaces yet.
7216 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7218 case Q3TCMOD_ROTATE:
7219 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7220 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7221 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7224 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7226 case Q3TCMOD_SCROLL:
7227 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7229 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7230 w = (int) tcmod->parms[0];
7231 h = (int) tcmod->parms[1];
7232 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7234 idx = (int) floor(f * w * h);
7235 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7237 case Q3TCMOD_STRETCH:
7238 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7239 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7241 case Q3TCMOD_TRANSFORM:
7242 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7243 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7244 VectorSet(tcmat + 6, 0 , 0 , 1);
7245 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7246 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7248 case Q3TCMOD_TURBULENT:
7249 // this is handled in the RSurf_PrepareVertices function
7250 matrix = identitymatrix;
7254 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7257 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7259 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7260 char name[MAX_QPATH];
7261 skinframe_t *skinframe;
7262 unsigned char pixels[296*194];
7263 strlcpy(cache->name, skinname, sizeof(cache->name));
7264 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7265 if (developer_loading.integer)
7266 Con_Printf("loading %s\n", name);
7267 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7268 if (!skinframe || !skinframe->base)
7271 fs_offset_t filesize;
7273 f = FS_LoadFile(name, tempmempool, true, &filesize);
7276 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7277 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7281 cache->skinframe = skinframe;
7284 texture_t *R_GetCurrentTexture(texture_t *t)
7287 const entity_render_t *ent = rsurface.entity;
7288 dp_model_t *model = ent->model;
7289 q3shaderinfo_layer_tcmod_t *tcmod;
7291 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7292 return t->currentframe;
7293 t->update_lastrenderframe = r_textureframe;
7294 t->update_lastrenderentity = (void *)ent;
7296 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7297 t->camera_entity = ent->entitynumber;
7299 t->camera_entity = 0;
7301 // switch to an alternate material if this is a q1bsp animated material
7303 texture_t *texture = t;
7304 int s = rsurface.ent_skinnum;
7305 if ((unsigned int)s >= (unsigned int)model->numskins)
7307 if (model->skinscenes)
7309 if (model->skinscenes[s].framecount > 1)
7310 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7312 s = model->skinscenes[s].firstframe;
7315 t = t + s * model->num_surfaces;
7318 // use an alternate animation if the entity's frame is not 0,
7319 // and only if the texture has an alternate animation
7320 if (rsurface.ent_alttextures && t->anim_total[1])
7321 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7323 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7325 texture->currentframe = t;
7328 // update currentskinframe to be a qw skin or animation frame
7329 if (rsurface.ent_qwskin >= 0)
7331 i = rsurface.ent_qwskin;
7332 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7334 r_qwskincache_size = cl.maxclients;
7336 Mem_Free(r_qwskincache);
7337 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7339 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7340 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7341 t->currentskinframe = r_qwskincache[i].skinframe;
7342 if (t->currentskinframe == NULL)
7343 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7345 else if (t->numskinframes >= 2)
7346 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7347 if (t->backgroundnumskinframes >= 2)
7348 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7350 t->currentmaterialflags = t->basematerialflags;
7351 t->currentalpha = rsurface.colormod[3];
7352 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7353 t->currentalpha *= r_wateralpha.value;
7354 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7355 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7356 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7357 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7358 if (!(rsurface.ent_flags & RENDER_LIGHT))
7359 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7360 else if (FAKELIGHT_ENABLED)
7362 // no modellight if using fakelight for the map
7364 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7366 // pick a model lighting mode
7367 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7368 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7370 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7372 if (rsurface.ent_flags & RENDER_ADDITIVE)
7373 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7374 else if (t->currentalpha < 1)
7375 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7376 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7377 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7378 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7379 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7380 if (t->backgroundnumskinframes)
7381 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7382 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7384 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7385 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7388 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7389 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7390 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7392 // there is no tcmod
7393 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7395 t->currenttexmatrix = r_waterscrollmatrix;
7396 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7398 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7400 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7401 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7404 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7405 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7406 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7407 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7409 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7410 if (t->currentskinframe->qpixels)
7411 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7412 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7413 if (!t->basetexture)
7414 t->basetexture = r_texture_notexture;
7415 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7416 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7417 t->nmaptexture = t->currentskinframe->nmap;
7418 if (!t->nmaptexture)
7419 t->nmaptexture = r_texture_blanknormalmap;
7420 t->glosstexture = r_texture_black;
7421 t->glowtexture = t->currentskinframe->glow;
7422 t->fogtexture = t->currentskinframe->fog;
7423 t->reflectmasktexture = t->currentskinframe->reflect;
7424 if (t->backgroundnumskinframes)
7426 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7427 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7428 t->backgroundglosstexture = r_texture_black;
7429 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7430 if (!t->backgroundnmaptexture)
7431 t->backgroundnmaptexture = r_texture_blanknormalmap;
7435 t->backgroundbasetexture = r_texture_white;
7436 t->backgroundnmaptexture = r_texture_blanknormalmap;
7437 t->backgroundglosstexture = r_texture_black;
7438 t->backgroundglowtexture = NULL;
7440 t->specularpower = r_shadow_glossexponent.value;
7441 // TODO: store reference values for these in the texture?
7442 t->specularscale = 0;
7443 if (r_shadow_gloss.integer > 0)
7445 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7447 if (r_shadow_glossintensity.value > 0)
7449 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7450 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7451 t->specularscale = r_shadow_glossintensity.value;
7454 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7456 t->glosstexture = r_texture_white;
7457 t->backgroundglosstexture = r_texture_white;
7458 t->specularscale = r_shadow_gloss2intensity.value;
7459 t->specularpower = r_shadow_gloss2exponent.value;
7462 t->specularscale *= t->specularscalemod;
7463 t->specularpower *= t->specularpowermod;
7465 // lightmaps mode looks bad with dlights using actual texturing, so turn
7466 // off the colormap and glossmap, but leave the normalmap on as it still
7467 // accurately represents the shading involved
7468 if (gl_lightmaps.integer)
7470 t->basetexture = r_texture_grey128;
7471 t->pantstexture = r_texture_black;
7472 t->shirttexture = r_texture_black;
7473 t->nmaptexture = r_texture_blanknormalmap;
7474 t->glosstexture = r_texture_black;
7475 t->glowtexture = NULL;
7476 t->fogtexture = NULL;
7477 t->reflectmasktexture = NULL;
7478 t->backgroundbasetexture = NULL;
7479 t->backgroundnmaptexture = r_texture_blanknormalmap;
7480 t->backgroundglosstexture = r_texture_black;
7481 t->backgroundglowtexture = NULL;
7482 t->specularscale = 0;
7483 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7486 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7487 VectorClear(t->dlightcolor);
7488 t->currentnumlayers = 0;
7489 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7491 int blendfunc1, blendfunc2;
7493 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7495 blendfunc1 = GL_SRC_ALPHA;
7496 blendfunc2 = GL_ONE;
7498 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7500 blendfunc1 = GL_SRC_ALPHA;
7501 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7503 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7505 blendfunc1 = t->customblendfunc[0];
7506 blendfunc2 = t->customblendfunc[1];
7510 blendfunc1 = GL_ONE;
7511 blendfunc2 = GL_ZERO;
7513 // don't colormod evilblend textures
7514 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7515 VectorSet(t->lightmapcolor, 1, 1, 1);
7516 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7517 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7519 // fullbright is not affected by r_refdef.lightmapintensity
7520 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]);
7521 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7522 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]);
7523 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7524 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]);
7528 vec3_t ambientcolor;
7530 // set the color tint used for lights affecting this surface
7531 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7533 // q3bsp has no lightmap updates, so the lightstylevalue that
7534 // would normally be baked into the lightmap must be
7535 // applied to the color
7536 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7537 if (model->type == mod_brushq3)
7538 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7539 colorscale *= r_refdef.lightmapintensity;
7540 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7541 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7542 // basic lit geometry
7543 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]);
7544 // add pants/shirt if needed
7545 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7546 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]);
7547 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7548 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]);
7549 // now add ambient passes if needed
7550 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7552 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]);
7553 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7554 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]);
7555 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7556 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]);
7559 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7560 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]);
7561 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7563 // if this is opaque use alpha blend which will darken the earlier
7566 // if this is an alpha blended material, all the earlier passes
7567 // were darkened by fog already, so we only need to add the fog
7568 // color ontop through the fog mask texture
7570 // if this is an additive blended material, all the earlier passes
7571 // were darkened by fog already, and we should not add fog color
7572 // (because the background was not darkened, there is no fog color
7573 // that was lost behind it).
7574 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]);
7578 return t->currentframe;
7581 rsurfacestate_t rsurface;
7583 void RSurf_ActiveWorldEntity(void)
7585 dp_model_t *model = r_refdef.scene.worldmodel;
7586 //if (rsurface.entity == r_refdef.scene.worldentity)
7588 rsurface.entity = r_refdef.scene.worldentity;
7589 rsurface.skeleton = NULL;
7590 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7591 rsurface.ent_skinnum = 0;
7592 rsurface.ent_qwskin = -1;
7593 rsurface.ent_shadertime = 0;
7594 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7595 rsurface.matrix = identitymatrix;
7596 rsurface.inversematrix = identitymatrix;
7597 rsurface.matrixscale = 1;
7598 rsurface.inversematrixscale = 1;
7599 R_EntityMatrix(&identitymatrix);
7600 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7601 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7602 rsurface.fograngerecip = r_refdef.fograngerecip;
7603 rsurface.fogheightfade = r_refdef.fogheightfade;
7604 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7605 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7606 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7607 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7608 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7609 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7610 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7611 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7612 rsurface.colormod[3] = 1;
7613 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);
7614 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7615 rsurface.frameblend[0].lerp = 1;
7616 rsurface.ent_alttextures = false;
7617 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7618 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7619 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7620 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7621 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7622 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7623 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7624 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7625 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7626 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7627 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7628 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7629 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7630 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7631 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7632 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7633 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7634 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7635 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7636 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7637 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7638 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7639 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7640 rsurface.modelelement3i = model->surfmesh.data_element3i;
7641 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7642 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7643 rsurface.modelelement3s = model->surfmesh.data_element3s;
7644 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7645 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7646 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7647 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7648 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7649 rsurface.modelsurfaces = model->data_surfaces;
7650 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7651 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7652 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7653 rsurface.modelgeneratedvertex = false;
7654 rsurface.batchgeneratedvertex = false;
7655 rsurface.batchfirstvertex = 0;
7656 rsurface.batchnumvertices = 0;
7657 rsurface.batchfirsttriangle = 0;
7658 rsurface.batchnumtriangles = 0;
7659 rsurface.batchvertex3f = NULL;
7660 rsurface.batchvertex3f_vertexbuffer = NULL;
7661 rsurface.batchvertex3f_bufferoffset = 0;
7662 rsurface.batchsvector3f = NULL;
7663 rsurface.batchsvector3f_vertexbuffer = NULL;
7664 rsurface.batchsvector3f_bufferoffset = 0;
7665 rsurface.batchtvector3f = NULL;
7666 rsurface.batchtvector3f_vertexbuffer = NULL;
7667 rsurface.batchtvector3f_bufferoffset = 0;
7668 rsurface.batchnormal3f = NULL;
7669 rsurface.batchnormal3f_vertexbuffer = NULL;
7670 rsurface.batchnormal3f_bufferoffset = 0;
7671 rsurface.batchlightmapcolor4f = NULL;
7672 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7673 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7674 rsurface.batchtexcoordtexture2f = NULL;
7675 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7676 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7677 rsurface.batchtexcoordlightmap2f = NULL;
7678 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7679 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7680 rsurface.batchvertexmesh = NULL;
7681 rsurface.batchvertexmeshbuffer = NULL;
7682 rsurface.batchvertex3fbuffer = NULL;
7683 rsurface.batchelement3i = NULL;
7684 rsurface.batchelement3i_indexbuffer = NULL;
7685 rsurface.batchelement3i_bufferoffset = 0;
7686 rsurface.batchelement3s = NULL;
7687 rsurface.batchelement3s_indexbuffer = NULL;
7688 rsurface.batchelement3s_bufferoffset = 0;
7689 rsurface.passcolor4f = NULL;
7690 rsurface.passcolor4f_vertexbuffer = NULL;
7691 rsurface.passcolor4f_bufferoffset = 0;
7694 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7696 dp_model_t *model = ent->model;
7697 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7699 rsurface.entity = (entity_render_t *)ent;
7700 rsurface.skeleton = ent->skeleton;
7701 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7702 rsurface.ent_skinnum = ent->skinnum;
7703 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;
7704 rsurface.ent_shadertime = ent->shadertime;
7705 rsurface.ent_flags = ent->flags;
7706 rsurface.matrix = ent->matrix;
7707 rsurface.inversematrix = ent->inversematrix;
7708 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7709 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7710 R_EntityMatrix(&rsurface.matrix);
7711 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7712 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7713 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7714 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7715 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7716 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7717 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7718 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7719 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7720 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7721 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7722 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7723 rsurface.colormod[3] = ent->alpha;
7724 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7725 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7726 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7727 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7728 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7729 if (ent->model->brush.submodel && !prepass)
7731 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7732 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7734 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7736 if (ent->animcache_vertex3f)
7738 rsurface.modelvertex3f = ent->animcache_vertex3f;
7739 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7740 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7741 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7742 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7743 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7744 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7746 else if (wanttangents)
7748 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7749 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7750 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7751 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7752 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7753 rsurface.modelvertexmesh = NULL;
7754 rsurface.modelvertexmeshbuffer = NULL;
7755 rsurface.modelvertex3fbuffer = NULL;
7757 else if (wantnormals)
7759 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7760 rsurface.modelsvector3f = NULL;
7761 rsurface.modeltvector3f = NULL;
7762 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7763 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7764 rsurface.modelvertexmesh = NULL;
7765 rsurface.modelvertexmeshbuffer = NULL;
7766 rsurface.modelvertex3fbuffer = NULL;
7770 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7771 rsurface.modelsvector3f = NULL;
7772 rsurface.modeltvector3f = NULL;
7773 rsurface.modelnormal3f = NULL;
7774 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7775 rsurface.modelvertexmesh = NULL;
7776 rsurface.modelvertexmeshbuffer = NULL;
7777 rsurface.modelvertex3fbuffer = NULL;
7779 rsurface.modelvertex3f_vertexbuffer = 0;
7780 rsurface.modelvertex3f_bufferoffset = 0;
7781 rsurface.modelsvector3f_vertexbuffer = 0;
7782 rsurface.modelsvector3f_bufferoffset = 0;
7783 rsurface.modeltvector3f_vertexbuffer = 0;
7784 rsurface.modeltvector3f_bufferoffset = 0;
7785 rsurface.modelnormal3f_vertexbuffer = 0;
7786 rsurface.modelnormal3f_bufferoffset = 0;
7787 rsurface.modelgeneratedvertex = true;
7791 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7792 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7793 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7794 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7795 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7797 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7798 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7800 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7801 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7802 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7803 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7804 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7805 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7806 rsurface.modelgeneratedvertex = false;
7808 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7809 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7810 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7811 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7812 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7813 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7814 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7815 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7816 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7817 rsurface.modelelement3i = model->surfmesh.data_element3i;
7818 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7819 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7820 rsurface.modelelement3s = model->surfmesh.data_element3s;
7821 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7822 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7823 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7824 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7825 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7826 rsurface.modelsurfaces = model->data_surfaces;
7827 rsurface.batchgeneratedvertex = false;
7828 rsurface.batchfirstvertex = 0;
7829 rsurface.batchnumvertices = 0;
7830 rsurface.batchfirsttriangle = 0;
7831 rsurface.batchnumtriangles = 0;
7832 rsurface.batchvertex3f = NULL;
7833 rsurface.batchvertex3f_vertexbuffer = NULL;
7834 rsurface.batchvertex3f_bufferoffset = 0;
7835 rsurface.batchsvector3f = NULL;
7836 rsurface.batchsvector3f_vertexbuffer = NULL;
7837 rsurface.batchsvector3f_bufferoffset = 0;
7838 rsurface.batchtvector3f = NULL;
7839 rsurface.batchtvector3f_vertexbuffer = NULL;
7840 rsurface.batchtvector3f_bufferoffset = 0;
7841 rsurface.batchnormal3f = NULL;
7842 rsurface.batchnormal3f_vertexbuffer = NULL;
7843 rsurface.batchnormal3f_bufferoffset = 0;
7844 rsurface.batchlightmapcolor4f = NULL;
7845 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7846 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7847 rsurface.batchtexcoordtexture2f = NULL;
7848 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7849 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7850 rsurface.batchtexcoordlightmap2f = NULL;
7851 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7852 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7853 rsurface.batchvertexmesh = NULL;
7854 rsurface.batchvertexmeshbuffer = NULL;
7855 rsurface.batchvertex3fbuffer = NULL;
7856 rsurface.batchelement3i = NULL;
7857 rsurface.batchelement3i_indexbuffer = NULL;
7858 rsurface.batchelement3i_bufferoffset = 0;
7859 rsurface.batchelement3s = NULL;
7860 rsurface.batchelement3s_indexbuffer = NULL;
7861 rsurface.batchelement3s_bufferoffset = 0;
7862 rsurface.passcolor4f = NULL;
7863 rsurface.passcolor4f_vertexbuffer = NULL;
7864 rsurface.passcolor4f_bufferoffset = 0;
7867 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)
7869 rsurface.entity = r_refdef.scene.worldentity;
7870 rsurface.skeleton = NULL;
7871 rsurface.ent_skinnum = 0;
7872 rsurface.ent_qwskin = -1;
7873 rsurface.ent_shadertime = shadertime;
7874 rsurface.ent_flags = entflags;
7875 rsurface.modelnumvertices = numvertices;
7876 rsurface.modelnumtriangles = numtriangles;
7877 rsurface.matrix = *matrix;
7878 rsurface.inversematrix = *inversematrix;
7879 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7880 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7881 R_EntityMatrix(&rsurface.matrix);
7882 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7883 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7884 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7885 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7886 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7887 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7888 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7889 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7890 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7891 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7892 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7893 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7894 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);
7895 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7896 rsurface.frameblend[0].lerp = 1;
7897 rsurface.ent_alttextures = false;
7898 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7899 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7902 rsurface.modelvertex3f = (float *)vertex3f;
7903 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7904 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7905 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7907 else if (wantnormals)
7909 rsurface.modelvertex3f = (float *)vertex3f;
7910 rsurface.modelsvector3f = NULL;
7911 rsurface.modeltvector3f = NULL;
7912 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7916 rsurface.modelvertex3f = (float *)vertex3f;
7917 rsurface.modelsvector3f = NULL;
7918 rsurface.modeltvector3f = NULL;
7919 rsurface.modelnormal3f = NULL;
7921 rsurface.modelvertexmesh = NULL;
7922 rsurface.modelvertexmeshbuffer = NULL;
7923 rsurface.modelvertex3fbuffer = NULL;
7924 rsurface.modelvertex3f_vertexbuffer = 0;
7925 rsurface.modelvertex3f_bufferoffset = 0;
7926 rsurface.modelsvector3f_vertexbuffer = 0;
7927 rsurface.modelsvector3f_bufferoffset = 0;
7928 rsurface.modeltvector3f_vertexbuffer = 0;
7929 rsurface.modeltvector3f_bufferoffset = 0;
7930 rsurface.modelnormal3f_vertexbuffer = 0;
7931 rsurface.modelnormal3f_bufferoffset = 0;
7932 rsurface.modelgeneratedvertex = true;
7933 rsurface.modellightmapcolor4f = (float *)color4f;
7934 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7935 rsurface.modellightmapcolor4f_bufferoffset = 0;
7936 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7937 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7938 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7939 rsurface.modeltexcoordlightmap2f = NULL;
7940 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7941 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7942 rsurface.modelelement3i = (int *)element3i;
7943 rsurface.modelelement3i_indexbuffer = NULL;
7944 rsurface.modelelement3i_bufferoffset = 0;
7945 rsurface.modelelement3s = (unsigned short *)element3s;
7946 rsurface.modelelement3s_indexbuffer = NULL;
7947 rsurface.modelelement3s_bufferoffset = 0;
7948 rsurface.modellightmapoffsets = NULL;
7949 rsurface.modelsurfaces = NULL;
7950 rsurface.batchgeneratedvertex = false;
7951 rsurface.batchfirstvertex = 0;
7952 rsurface.batchnumvertices = 0;
7953 rsurface.batchfirsttriangle = 0;
7954 rsurface.batchnumtriangles = 0;
7955 rsurface.batchvertex3f = NULL;
7956 rsurface.batchvertex3f_vertexbuffer = NULL;
7957 rsurface.batchvertex3f_bufferoffset = 0;
7958 rsurface.batchsvector3f = NULL;
7959 rsurface.batchsvector3f_vertexbuffer = NULL;
7960 rsurface.batchsvector3f_bufferoffset = 0;
7961 rsurface.batchtvector3f = NULL;
7962 rsurface.batchtvector3f_vertexbuffer = NULL;
7963 rsurface.batchtvector3f_bufferoffset = 0;
7964 rsurface.batchnormal3f = NULL;
7965 rsurface.batchnormal3f_vertexbuffer = NULL;
7966 rsurface.batchnormal3f_bufferoffset = 0;
7967 rsurface.batchlightmapcolor4f = NULL;
7968 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7969 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7970 rsurface.batchtexcoordtexture2f = NULL;
7971 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7972 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7973 rsurface.batchtexcoordlightmap2f = NULL;
7974 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7975 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7976 rsurface.batchvertexmesh = NULL;
7977 rsurface.batchvertexmeshbuffer = NULL;
7978 rsurface.batchvertex3fbuffer = NULL;
7979 rsurface.batchelement3i = NULL;
7980 rsurface.batchelement3i_indexbuffer = NULL;
7981 rsurface.batchelement3i_bufferoffset = 0;
7982 rsurface.batchelement3s = NULL;
7983 rsurface.batchelement3s_indexbuffer = NULL;
7984 rsurface.batchelement3s_bufferoffset = 0;
7985 rsurface.passcolor4f = NULL;
7986 rsurface.passcolor4f_vertexbuffer = NULL;
7987 rsurface.passcolor4f_bufferoffset = 0;
7989 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7991 if ((wantnormals || wanttangents) && !normal3f)
7993 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7994 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7996 if (wanttangents && !svector3f)
7998 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7999 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8000 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8005 float RSurf_FogPoint(const float *v)
8007 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8008 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8009 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8010 float FogHeightFade = r_refdef.fogheightfade;
8012 unsigned int fogmasktableindex;
8013 if (r_refdef.fogplaneviewabove)
8014 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8016 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8017 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8018 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8021 float RSurf_FogVertex(const float *v)
8023 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8024 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8025 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8026 float FogHeightFade = rsurface.fogheightfade;
8028 unsigned int fogmasktableindex;
8029 if (r_refdef.fogplaneviewabove)
8030 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8032 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8033 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8034 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8037 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8040 for (i = 0;i < numelements;i++)
8041 outelement3i[i] = inelement3i[i] + adjust;
8044 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8045 extern cvar_t gl_vbo;
8046 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8054 int surfacefirsttriangle;
8055 int surfacenumtriangles;
8056 int surfacefirstvertex;
8057 int surfaceendvertex;
8058 int surfacenumvertices;
8059 int batchnumvertices;
8060 int batchnumtriangles;
8064 qboolean dynamicvertex;
8068 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8070 q3shaderinfo_deform_t *deform;
8071 const msurface_t *surface, *firstsurface;
8072 r_vertexmesh_t *vertexmesh;
8073 if (!texturenumsurfaces)
8075 // find vertex range of this surface batch
8077 firstsurface = texturesurfacelist[0];
8078 firsttriangle = firstsurface->num_firsttriangle;
8079 batchnumvertices = 0;
8080 batchnumtriangles = 0;
8081 firstvertex = endvertex = firstsurface->num_firstvertex;
8082 for (i = 0;i < texturenumsurfaces;i++)
8084 surface = texturesurfacelist[i];
8085 if (surface != firstsurface + i)
8087 surfacefirstvertex = surface->num_firstvertex;
8088 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8089 surfacenumvertices = surface->num_vertices;
8090 surfacenumtriangles = surface->num_triangles;
8091 if (firstvertex > surfacefirstvertex)
8092 firstvertex = surfacefirstvertex;
8093 if (endvertex < surfaceendvertex)
8094 endvertex = surfaceendvertex;
8095 batchnumvertices += surfacenumvertices;
8096 batchnumtriangles += surfacenumtriangles;
8099 // we now know the vertex range used, and if there are any gaps in it
8100 rsurface.batchfirstvertex = firstvertex;
8101 rsurface.batchnumvertices = endvertex - firstvertex;
8102 rsurface.batchfirsttriangle = firsttriangle;
8103 rsurface.batchnumtriangles = batchnumtriangles;
8105 // this variable holds flags for which properties have been updated that
8106 // may require regenerating vertexmesh array...
8109 // check if any dynamic vertex processing must occur
8110 dynamicvertex = false;
8112 // if there is a chance of animated vertex colors, it's a dynamic batch
8113 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8115 dynamicvertex = true;
8116 batchneed |= BATCHNEED_NOGAPS;
8117 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8120 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8122 switch (deform->deform)
8125 case Q3DEFORM_PROJECTIONSHADOW:
8126 case Q3DEFORM_TEXT0:
8127 case Q3DEFORM_TEXT1:
8128 case Q3DEFORM_TEXT2:
8129 case Q3DEFORM_TEXT3:
8130 case Q3DEFORM_TEXT4:
8131 case Q3DEFORM_TEXT5:
8132 case Q3DEFORM_TEXT6:
8133 case Q3DEFORM_TEXT7:
8136 case Q3DEFORM_AUTOSPRITE:
8137 dynamicvertex = true;
8138 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8139 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8141 case Q3DEFORM_AUTOSPRITE2:
8142 dynamicvertex = true;
8143 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8144 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8146 case Q3DEFORM_NORMAL:
8147 dynamicvertex = true;
8148 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8149 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8152 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8153 break; // if wavefunc is a nop, ignore this transform
8154 dynamicvertex = true;
8155 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8156 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8158 case Q3DEFORM_BULGE:
8159 dynamicvertex = true;
8160 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8161 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8164 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8165 break; // if wavefunc is a nop, ignore this transform
8166 dynamicvertex = true;
8167 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8168 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8172 switch(rsurface.texture->tcgen.tcgen)
8175 case Q3TCGEN_TEXTURE:
8177 case Q3TCGEN_LIGHTMAP:
8178 dynamicvertex = true;
8179 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8180 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8182 case Q3TCGEN_VECTOR:
8183 dynamicvertex = true;
8184 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8185 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8187 case Q3TCGEN_ENVIRONMENT:
8188 dynamicvertex = true;
8189 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8190 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8193 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8195 dynamicvertex = true;
8196 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8197 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8200 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8202 dynamicvertex = true;
8203 batchneed |= BATCHNEED_NOGAPS;
8204 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8207 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8209 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8210 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8211 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8212 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8213 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8214 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8215 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8218 // when the model data has no vertex buffer (dynamic mesh), we need to
8220 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8221 batchneed |= BATCHNEED_NOGAPS;
8223 // if needsupdate, we have to do a dynamic vertex batch for sure
8224 if (needsupdate & batchneed)
8225 dynamicvertex = true;
8227 // see if we need to build vertexmesh from arrays
8228 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8229 dynamicvertex = true;
8231 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8232 // also some drivers strongly dislike firstvertex
8233 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8234 dynamicvertex = true;
8236 rsurface.batchvertex3f = rsurface.modelvertex3f;
8237 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8238 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8239 rsurface.batchsvector3f = rsurface.modelsvector3f;
8240 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8241 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8242 rsurface.batchtvector3f = rsurface.modeltvector3f;
8243 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8244 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8245 rsurface.batchnormal3f = rsurface.modelnormal3f;
8246 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8247 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8248 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8249 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8250 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8251 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8252 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8253 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8254 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8255 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8256 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8257 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8258 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8259 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8260 rsurface.batchelement3i = rsurface.modelelement3i;
8261 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8262 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8263 rsurface.batchelement3s = rsurface.modelelement3s;
8264 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8265 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8267 // if any dynamic vertex processing has to occur in software, we copy the
8268 // entire surface list together before processing to rebase the vertices
8269 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8271 // if any gaps exist and we do not have a static vertex buffer, we have to
8272 // copy the surface list together to avoid wasting upload bandwidth on the
8273 // vertices in the gaps.
8275 // if gaps exist and we have a static vertex buffer, we still have to
8276 // combine the index buffer ranges into one dynamic index buffer.
8278 // in all cases we end up with data that can be drawn in one call.
8282 // static vertex data, just set pointers...
8283 rsurface.batchgeneratedvertex = false;
8284 // if there are gaps, we want to build a combined index buffer,
8285 // otherwise use the original static buffer with an appropriate offset
8288 // build a new triangle elements array for this batch
8289 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8290 rsurface.batchfirsttriangle = 0;
8292 for (i = 0;i < texturenumsurfaces;i++)
8294 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8295 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8296 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8297 numtriangles += surfacenumtriangles;
8299 rsurface.batchelement3i_indexbuffer = NULL;
8300 rsurface.batchelement3i_bufferoffset = 0;
8301 rsurface.batchelement3s = NULL;
8302 rsurface.batchelement3s_indexbuffer = NULL;
8303 rsurface.batchelement3s_bufferoffset = 0;
8304 if (endvertex <= 65536)
8306 // make a 16bit (unsigned short) index array if possible
8307 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8308 for (i = 0;i < numtriangles*3;i++)
8309 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8315 // something needs software processing, do it for real...
8316 // we only directly handle separate array data in this case and then
8317 // generate interleaved data if needed...
8318 rsurface.batchgeneratedvertex = true;
8320 // now copy the vertex data into a combined array and make an index array
8321 // (this is what Quake3 does all the time)
8322 //if (gaps || rsurface.batchfirstvertex)
8324 rsurface.batchvertex3fbuffer = NULL;
8325 rsurface.batchvertexmesh = NULL;
8326 rsurface.batchvertexmeshbuffer = NULL;
8327 rsurface.batchvertex3f = NULL;
8328 rsurface.batchvertex3f_vertexbuffer = NULL;
8329 rsurface.batchvertex3f_bufferoffset = 0;
8330 rsurface.batchsvector3f = NULL;
8331 rsurface.batchsvector3f_vertexbuffer = NULL;
8332 rsurface.batchsvector3f_bufferoffset = 0;
8333 rsurface.batchtvector3f = NULL;
8334 rsurface.batchtvector3f_vertexbuffer = NULL;
8335 rsurface.batchtvector3f_bufferoffset = 0;
8336 rsurface.batchnormal3f = NULL;
8337 rsurface.batchnormal3f_vertexbuffer = NULL;
8338 rsurface.batchnormal3f_bufferoffset = 0;
8339 rsurface.batchlightmapcolor4f = NULL;
8340 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8341 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8342 rsurface.batchtexcoordtexture2f = NULL;
8343 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8344 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8345 rsurface.batchtexcoordlightmap2f = NULL;
8346 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8347 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8348 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8349 rsurface.batchelement3i_indexbuffer = NULL;
8350 rsurface.batchelement3i_bufferoffset = 0;
8351 rsurface.batchelement3s = NULL;
8352 rsurface.batchelement3s_indexbuffer = NULL;
8353 rsurface.batchelement3s_bufferoffset = 0;
8354 // we'll only be setting up certain arrays as needed
8355 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8356 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8357 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8358 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8359 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8360 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8361 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8363 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8364 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8366 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8367 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8368 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8369 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8370 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8371 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8374 for (i = 0;i < texturenumsurfaces;i++)
8376 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8377 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8378 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8379 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8380 // copy only the data requested
8381 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8382 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8383 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8385 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8386 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8387 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8388 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8389 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8391 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8392 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8394 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8395 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8396 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8397 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8398 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8399 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8401 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8402 numvertices += surfacenumvertices;
8403 numtriangles += surfacenumtriangles;
8406 // generate a 16bit index array as well if possible
8407 // (in general, dynamic batches fit)
8408 if (numvertices <= 65536)
8410 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8411 for (i = 0;i < numtriangles*3;i++)
8412 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8415 // since we've copied everything, the batch now starts at 0
8416 rsurface.batchfirstvertex = 0;
8417 rsurface.batchnumvertices = batchnumvertices;
8418 rsurface.batchfirsttriangle = 0;
8419 rsurface.batchnumtriangles = batchnumtriangles;
8422 // q1bsp surfaces rendered in vertex color mode have to have colors
8423 // calculated based on lightstyles
8424 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8426 // generate color arrays for the surfaces in this list
8431 const unsigned char *lm;
8432 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8433 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8434 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8436 for (i = 0;i < texturenumsurfaces;i++)
8438 surface = texturesurfacelist[i];
8439 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8440 surfacenumvertices = surface->num_vertices;
8441 if (surface->lightmapinfo->samples)
8443 for (j = 0;j < surfacenumvertices;j++)
8445 lm = surface->lightmapinfo->samples + offsets[j];
8446 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8447 VectorScale(lm, scale, c);
8448 if (surface->lightmapinfo->styles[1] != 255)
8450 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8452 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8453 VectorMA(c, scale, lm, c);
8454 if (surface->lightmapinfo->styles[2] != 255)
8457 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8458 VectorMA(c, scale, lm, c);
8459 if (surface->lightmapinfo->styles[3] != 255)
8462 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8463 VectorMA(c, scale, lm, c);
8470 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);
8476 for (j = 0;j < surfacenumvertices;j++)
8478 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8485 // if vertices are deformed (sprite flares and things in maps, possibly
8486 // water waves, bulges and other deformations), modify the copied vertices
8488 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8490 switch (deform->deform)
8493 case Q3DEFORM_PROJECTIONSHADOW:
8494 case Q3DEFORM_TEXT0:
8495 case Q3DEFORM_TEXT1:
8496 case Q3DEFORM_TEXT2:
8497 case Q3DEFORM_TEXT3:
8498 case Q3DEFORM_TEXT4:
8499 case Q3DEFORM_TEXT5:
8500 case Q3DEFORM_TEXT6:
8501 case Q3DEFORM_TEXT7:
8504 case Q3DEFORM_AUTOSPRITE:
8505 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8506 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8507 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8508 VectorNormalize(newforward);
8509 VectorNormalize(newright);
8510 VectorNormalize(newup);
8511 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8512 // rsurface.batchvertex3f_vertexbuffer = NULL;
8513 // rsurface.batchvertex3f_bufferoffset = 0;
8514 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8515 // rsurface.batchsvector3f_vertexbuffer = NULL;
8516 // rsurface.batchsvector3f_bufferoffset = 0;
8517 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8518 // rsurface.batchtvector3f_vertexbuffer = NULL;
8519 // rsurface.batchtvector3f_bufferoffset = 0;
8520 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8521 // rsurface.batchnormal3f_vertexbuffer = NULL;
8522 // rsurface.batchnormal3f_bufferoffset = 0;
8523 // a single autosprite surface can contain multiple sprites...
8524 for (j = 0;j < batchnumvertices - 3;j += 4)
8526 VectorClear(center);
8527 for (i = 0;i < 4;i++)
8528 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8529 VectorScale(center, 0.25f, center);
8530 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8531 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8532 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8533 for (i = 0;i < 4;i++)
8535 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8536 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8539 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8540 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8541 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);
8543 case Q3DEFORM_AUTOSPRITE2:
8544 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8545 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8546 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8547 VectorNormalize(newforward);
8548 VectorNormalize(newright);
8549 VectorNormalize(newup);
8550 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8551 // rsurface.batchvertex3f_vertexbuffer = NULL;
8552 // rsurface.batchvertex3f_bufferoffset = 0;
8554 const float *v1, *v2;
8564 memset(shortest, 0, sizeof(shortest));
8565 // a single autosprite surface can contain multiple sprites...
8566 for (j = 0;j < batchnumvertices - 3;j += 4)
8568 VectorClear(center);
8569 for (i = 0;i < 4;i++)
8570 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8571 VectorScale(center, 0.25f, center);
8572 // find the two shortest edges, then use them to define the
8573 // axis vectors for rotating around the central axis
8574 for (i = 0;i < 6;i++)
8576 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8577 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8578 l = VectorDistance2(v1, v2);
8579 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8581 l += (1.0f / 1024.0f);
8582 if (shortest[0].length2 > l || i == 0)
8584 shortest[1] = shortest[0];
8585 shortest[0].length2 = l;
8586 shortest[0].v1 = v1;
8587 shortest[0].v2 = v2;
8589 else if (shortest[1].length2 > l || i == 1)
8591 shortest[1].length2 = l;
8592 shortest[1].v1 = v1;
8593 shortest[1].v2 = v2;
8596 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8597 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8598 // this calculates the right vector from the shortest edge
8599 // and the up vector from the edge midpoints
8600 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8601 VectorNormalize(right);
8602 VectorSubtract(end, start, up);
8603 VectorNormalize(up);
8604 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8605 VectorSubtract(rsurface.localvieworigin, center, forward);
8606 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8607 VectorNegate(forward, forward);
8608 VectorReflect(forward, 0, up, forward);
8609 VectorNormalize(forward);
8610 CrossProduct(up, forward, newright);
8611 VectorNormalize(newright);
8612 // rotate the quad around the up axis vector, this is made
8613 // especially easy by the fact we know the quad is flat,
8614 // so we only have to subtract the center position and
8615 // measure distance along the right vector, and then
8616 // multiply that by the newright vector and add back the
8618 // we also need to subtract the old position to undo the
8619 // displacement from the center, which we do with a
8620 // DotProduct, the subtraction/addition of center is also
8621 // optimized into DotProducts here
8622 l = DotProduct(right, center);
8623 for (i = 0;i < 4;i++)
8625 v1 = rsurface.batchvertex3f + 3*(j+i);
8626 f = DotProduct(right, v1) - l;
8627 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8631 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8633 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8634 // rsurface.batchnormal3f_vertexbuffer = NULL;
8635 // rsurface.batchnormal3f_bufferoffset = 0;
8636 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
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);
8649 case Q3DEFORM_NORMAL:
8650 // deform the normals to make reflections wavey
8651 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8652 rsurface.batchnormal3f_vertexbuffer = NULL;
8653 rsurface.batchnormal3f_bufferoffset = 0;
8654 for (j = 0;j < batchnumvertices;j++)
8657 float *normal = rsurface.batchnormal3f + 3*j;
8658 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8659 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8660 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]);
8661 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]);
8662 VectorNormalize(normal);
8664 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8666 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8667 // rsurface.batchsvector3f_vertexbuffer = NULL;
8668 // rsurface.batchsvector3f_bufferoffset = 0;
8669 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8670 // rsurface.batchtvector3f_vertexbuffer = NULL;
8671 // rsurface.batchtvector3f_bufferoffset = 0;
8672 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);
8676 // deform vertex array to make wavey water and flags and such
8677 waveparms[0] = deform->waveparms[0];
8678 waveparms[1] = deform->waveparms[1];
8679 waveparms[2] = deform->waveparms[2];
8680 waveparms[3] = deform->waveparms[3];
8681 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8682 break; // if wavefunc is a nop, don't make a dynamic vertex array
8683 // this is how a divisor of vertex influence on deformation
8684 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8685 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8686 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8687 // rsurface.batchvertex3f_vertexbuffer = NULL;
8688 // rsurface.batchvertex3f_bufferoffset = 0;
8689 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8690 // rsurface.batchnormal3f_vertexbuffer = NULL;
8691 // rsurface.batchnormal3f_bufferoffset = 0;
8692 for (j = 0;j < batchnumvertices;j++)
8694 // if the wavefunc depends on time, evaluate it per-vertex
8697 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8698 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
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);
8715 case Q3DEFORM_BULGE:
8716 // deform vertex array to make the surface have moving bulges
8717 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8718 // rsurface.batchvertex3f_vertexbuffer = NULL;
8719 // rsurface.batchvertex3f_bufferoffset = 0;
8720 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8721 // rsurface.batchnormal3f_vertexbuffer = NULL;
8722 // rsurface.batchnormal3f_bufferoffset = 0;
8723 for (j = 0;j < batchnumvertices;j++)
8725 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8726 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8728 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8729 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8730 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8732 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8733 // rsurface.batchsvector3f_vertexbuffer = NULL;
8734 // rsurface.batchsvector3f_bufferoffset = 0;
8735 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8736 // rsurface.batchtvector3f_vertexbuffer = NULL;
8737 // rsurface.batchtvector3f_bufferoffset = 0;
8738 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);
8742 // deform vertex array
8743 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8744 break; // if wavefunc is a nop, don't make a dynamic vertex array
8745 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8746 VectorScale(deform->parms, scale, waveparms);
8747 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8748 // rsurface.batchvertex3f_vertexbuffer = NULL;
8749 // rsurface.batchvertex3f_bufferoffset = 0;
8750 for (j = 0;j < batchnumvertices;j++)
8751 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8756 // generate texcoords based on the chosen texcoord source
8757 switch(rsurface.texture->tcgen.tcgen)
8760 case Q3TCGEN_TEXTURE:
8762 case Q3TCGEN_LIGHTMAP:
8763 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8764 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8765 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8766 if (rsurface.batchtexcoordlightmap2f)
8767 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8769 case Q3TCGEN_VECTOR:
8770 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8771 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8772 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8773 for (j = 0;j < batchnumvertices;j++)
8775 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8776 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8779 case Q3TCGEN_ENVIRONMENT:
8780 // make environment reflections using a spheremap
8781 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8782 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8783 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8784 for (j = 0;j < batchnumvertices;j++)
8786 // identical to Q3A's method, but executed in worldspace so
8787 // carried models can be shiny too
8789 float viewer[3], d, reflected[3], worldreflected[3];
8791 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8792 // VectorNormalize(viewer);
8794 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8796 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8797 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8798 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8799 // note: this is proportinal to viewer, so we can normalize later
8801 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8802 VectorNormalize(worldreflected);
8804 // note: this sphere map only uses world x and z!
8805 // so positive and negative y will LOOK THE SAME.
8806 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8807 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8811 // the only tcmod that needs software vertex processing is turbulent, so
8812 // check for it here and apply the changes if needed
8813 // and we only support that as the first one
8814 // (handling a mixture of turbulent and other tcmods would be problematic
8815 // without punting it entirely to a software path)
8816 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8818 amplitude = rsurface.texture->tcmods[0].parms[1];
8819 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8820 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8821 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8822 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8823 for (j = 0;j < batchnumvertices;j++)
8825 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);
8826 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8830 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8832 // convert the modified arrays to vertex structs
8833 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8834 // rsurface.batchvertexmeshbuffer = NULL;
8835 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8836 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8837 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8838 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8839 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8840 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8841 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8843 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8845 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8846 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8849 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8850 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8851 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8852 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8853 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8854 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8855 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8856 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8857 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8861 void RSurf_DrawBatch(void)
8863 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8864 // through the pipeline, killing it earlier in the pipeline would have
8865 // per-surface overhead rather than per-batch overhead, so it's best to
8866 // reject it here, before it hits glDraw.
8867 if (rsurface.batchnumtriangles == 0)
8870 // batch debugging code
8871 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8877 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8878 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8881 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8883 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8885 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8886 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);
8893 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);
8896 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8898 // pick the closest matching water plane
8899 int planeindex, vertexindex, bestplaneindex = -1;
8903 r_waterstate_waterplane_t *p;
8904 qboolean prepared = false;
8906 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8908 if(p->camera_entity != rsurface.texture->camera_entity)
8913 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8915 if(rsurface.batchnumvertices == 0)
8918 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8920 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8921 d += fabs(PlaneDiff(vert, &p->plane));
8923 if (bestd > d || bestplaneindex < 0)
8926 bestplaneindex = planeindex;
8929 return bestplaneindex;
8930 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8931 // this situation though, as it might be better to render single larger
8932 // batches with useless stuff (backface culled for example) than to
8933 // render multiple smaller batches
8936 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8939 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8940 rsurface.passcolor4f_vertexbuffer = 0;
8941 rsurface.passcolor4f_bufferoffset = 0;
8942 for (i = 0;i < rsurface.batchnumvertices;i++)
8943 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8946 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8953 if (rsurface.passcolor4f)
8955 // generate color arrays
8956 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8957 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8958 rsurface.passcolor4f_vertexbuffer = 0;
8959 rsurface.passcolor4f_bufferoffset = 0;
8960 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)
8962 f = RSurf_FogVertex(v);
8971 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8972 rsurface.passcolor4f_vertexbuffer = 0;
8973 rsurface.passcolor4f_bufferoffset = 0;
8974 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8976 f = RSurf_FogVertex(v);
8985 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8992 if (!rsurface.passcolor4f)
8994 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8995 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8996 rsurface.passcolor4f_vertexbuffer = 0;
8997 rsurface.passcolor4f_bufferoffset = 0;
8998 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)
9000 f = RSurf_FogVertex(v);
9001 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9002 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9003 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9008 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9013 if (!rsurface.passcolor4f)
9015 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9016 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9017 rsurface.passcolor4f_vertexbuffer = 0;
9018 rsurface.passcolor4f_bufferoffset = 0;
9019 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9028 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9033 if (!rsurface.passcolor4f)
9035 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9036 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9037 rsurface.passcolor4f_vertexbuffer = 0;
9038 rsurface.passcolor4f_bufferoffset = 0;
9039 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9041 c2[0] = c[0] + r_refdef.scene.ambient;
9042 c2[1] = c[1] + r_refdef.scene.ambient;
9043 c2[2] = c[2] + r_refdef.scene.ambient;
9048 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9051 rsurface.passcolor4f = NULL;
9052 rsurface.passcolor4f_vertexbuffer = 0;
9053 rsurface.passcolor4f_bufferoffset = 0;
9054 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9055 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9056 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9057 GL_Color(r, g, b, a);
9058 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9062 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9064 // TODO: optimize applyfog && applycolor case
9065 // just apply fog if necessary, and tint the fog color array if necessary
9066 rsurface.passcolor4f = NULL;
9067 rsurface.passcolor4f_vertexbuffer = 0;
9068 rsurface.passcolor4f_bufferoffset = 0;
9069 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9070 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9071 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9072 GL_Color(r, g, b, a);
9076 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9079 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9080 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9081 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9082 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9083 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9084 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9085 GL_Color(r, g, b, a);
9089 static void RSurf_DrawBatch_GL11_ClampColor(void)
9094 if (!rsurface.passcolor4f)
9096 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9098 c2[0] = bound(0.0f, c1[0], 1.0f);
9099 c2[1] = bound(0.0f, c1[1], 1.0f);
9100 c2[2] = bound(0.0f, c1[2], 1.0f);
9101 c2[3] = bound(0.0f, c1[3], 1.0f);
9105 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9115 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9116 rsurface.passcolor4f_vertexbuffer = 0;
9117 rsurface.passcolor4f_bufferoffset = 0;
9118 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)
9120 f = -DotProduct(r_refdef.view.forward, n);
9122 f = f * 0.85 + 0.15; // work around so stuff won't get black
9123 f *= r_refdef.lightmapintensity;
9124 Vector4Set(c, f, f, f, 1);
9128 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9130 RSurf_DrawBatch_GL11_ApplyFakeLight();
9131 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9132 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9133 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9134 GL_Color(r, g, b, a);
9138 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9146 vec3_t ambientcolor;
9147 vec3_t diffusecolor;
9151 VectorCopy(rsurface.modellight_lightdir, lightdir);
9152 f = 0.5f * r_refdef.lightmapintensity;
9153 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9154 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9155 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9156 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9157 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9158 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9160 if (VectorLength2(diffusecolor) > 0)
9162 // q3-style directional shading
9163 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9164 rsurface.passcolor4f_vertexbuffer = 0;
9165 rsurface.passcolor4f_bufferoffset = 0;
9166 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)
9168 if ((f = DotProduct(n, lightdir)) > 0)
9169 VectorMA(ambientcolor, f, diffusecolor, c);
9171 VectorCopy(ambientcolor, c);
9178 *applycolor = false;
9182 *r = ambientcolor[0];
9183 *g = ambientcolor[1];
9184 *b = ambientcolor[2];
9185 rsurface.passcolor4f = NULL;
9186 rsurface.passcolor4f_vertexbuffer = 0;
9187 rsurface.passcolor4f_bufferoffset = 0;
9191 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9193 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9194 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9195 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9196 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9197 GL_Color(r, g, b, a);
9201 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9207 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9209 f = 1 - RSurf_FogVertex(v);
9217 void RSurf_SetupDepthAndCulling(void)
9219 // submodels are biased to avoid z-fighting with world surfaces that they
9220 // may be exactly overlapping (avoids z-fighting artifacts on certain
9221 // doors and things in Quake maps)
9222 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9223 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9224 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9225 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9228 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9230 // transparent sky would be ridiculous
9231 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9233 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9234 skyrenderlater = true;
9235 RSurf_SetupDepthAndCulling();
9237 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9238 // skymasking on them, and Quake3 never did sky masking (unlike
9239 // software Quake and software Quake2), so disable the sky masking
9240 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9241 // and skymasking also looks very bad when noclipping outside the
9242 // level, so don't use it then either.
9243 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9245 R_Mesh_ResetTextureState();
9246 if (skyrendermasked)
9248 R_SetupShader_DepthOrShadow();
9249 // depth-only (masking)
9250 GL_ColorMask(0,0,0,0);
9251 // just to make sure that braindead drivers don't draw
9252 // anything despite that colormask...
9253 GL_BlendFunc(GL_ZERO, GL_ONE);
9254 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9255 if (rsurface.batchvertex3fbuffer)
9256 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9258 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9262 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9264 GL_BlendFunc(GL_ONE, GL_ZERO);
9265 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9266 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9267 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9270 if (skyrendermasked)
9271 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9273 R_Mesh_ResetTextureState();
9274 GL_Color(1, 1, 1, 1);
9277 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9278 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9279 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9281 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9285 // render screenspace normalmap to texture
9287 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9292 // bind lightmap texture
9294 // water/refraction/reflection/camera surfaces have to be handled specially
9295 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9297 int start, end, startplaneindex;
9298 for (start = 0;start < texturenumsurfaces;start = end)
9300 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9301 if(startplaneindex < 0)
9303 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9304 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9308 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9310 // now that we have a batch using the same planeindex, render it
9311 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9313 // render water or distortion background
9315 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));
9317 // blend surface on top
9318 GL_DepthMask(false);
9319 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9322 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9324 // render surface with reflection texture as input
9325 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9326 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));
9333 // render surface batch normally
9334 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9335 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9339 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9341 // OpenGL 1.3 path - anything not completely ancient
9342 qboolean applycolor;
9345 const texturelayer_t *layer;
9346 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);
9347 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9349 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9352 int layertexrgbscale;
9353 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9355 if (layerindex == 0)
9359 GL_AlphaTest(false);
9360 GL_DepthFunc(GL_EQUAL);
9363 GL_DepthMask(layer->depthmask && writedepth);
9364 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9365 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9367 layertexrgbscale = 4;
9368 VectorScale(layer->color, 0.25f, layercolor);
9370 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9372 layertexrgbscale = 2;
9373 VectorScale(layer->color, 0.5f, layercolor);
9377 layertexrgbscale = 1;
9378 VectorScale(layer->color, 1.0f, layercolor);
9380 layercolor[3] = layer->color[3];
9381 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9382 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9383 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9384 switch (layer->type)
9386 case TEXTURELAYERTYPE_LITTEXTURE:
9387 // single-pass lightmapped texture with 2x rgbscale
9388 R_Mesh_TexBind(0, r_texture_white);
9389 R_Mesh_TexMatrix(0, NULL);
9390 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9391 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9392 R_Mesh_TexBind(1, layer->texture);
9393 R_Mesh_TexMatrix(1, &layer->texmatrix);
9394 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9395 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9396 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9397 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9398 else if (FAKELIGHT_ENABLED)
9399 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9400 else if (rsurface.uselightmaptexture)
9401 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9403 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9405 case TEXTURELAYERTYPE_TEXTURE:
9406 // singletexture unlit texture with transparency support
9407 R_Mesh_TexBind(0, layer->texture);
9408 R_Mesh_TexMatrix(0, &layer->texmatrix);
9409 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9410 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9411 R_Mesh_TexBind(1, 0);
9412 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9413 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9415 case TEXTURELAYERTYPE_FOG:
9416 // singletexture fogging
9419 R_Mesh_TexBind(0, layer->texture);
9420 R_Mesh_TexMatrix(0, &layer->texmatrix);
9421 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9422 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9426 R_Mesh_TexBind(0, 0);
9427 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9429 R_Mesh_TexBind(1, 0);
9430 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9431 // generate a color array for the fog pass
9432 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9433 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9437 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9440 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9442 GL_DepthFunc(GL_LEQUAL);
9443 GL_AlphaTest(false);
9447 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9449 // OpenGL 1.1 - crusty old voodoo path
9452 const texturelayer_t *layer;
9453 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);
9454 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9456 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9458 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9460 if (layerindex == 0)
9464 GL_AlphaTest(false);
9465 GL_DepthFunc(GL_EQUAL);
9468 GL_DepthMask(layer->depthmask && writedepth);
9469 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9470 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9471 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9472 switch (layer->type)
9474 case TEXTURELAYERTYPE_LITTEXTURE:
9475 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9477 // two-pass lit texture with 2x rgbscale
9478 // first the lightmap pass
9479 R_Mesh_TexBind(0, r_texture_white);
9480 R_Mesh_TexMatrix(0, NULL);
9481 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9482 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9483 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9484 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9485 else if (FAKELIGHT_ENABLED)
9486 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9487 else if (rsurface.uselightmaptexture)
9488 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9490 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9491 // then apply the texture to it
9492 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9493 R_Mesh_TexBind(0, layer->texture);
9494 R_Mesh_TexMatrix(0, &layer->texmatrix);
9495 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9496 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9497 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);
9501 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9502 R_Mesh_TexBind(0, layer->texture);
9503 R_Mesh_TexMatrix(0, &layer->texmatrix);
9504 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9505 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9506 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9507 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);
9509 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);
9512 case TEXTURELAYERTYPE_TEXTURE:
9513 // singletexture unlit texture with transparency support
9514 R_Mesh_TexBind(0, layer->texture);
9515 R_Mesh_TexMatrix(0, &layer->texmatrix);
9516 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9517 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9518 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);
9520 case TEXTURELAYERTYPE_FOG:
9521 // singletexture fogging
9524 R_Mesh_TexBind(0, layer->texture);
9525 R_Mesh_TexMatrix(0, &layer->texmatrix);
9526 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9527 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9531 R_Mesh_TexBind(0, 0);
9532 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9534 // generate a color array for the fog pass
9535 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9536 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9540 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9543 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9545 GL_DepthFunc(GL_LEQUAL);
9546 GL_AlphaTest(false);
9550 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9554 r_vertexgeneric_t *batchvertex;
9557 // R_Mesh_ResetTextureState();
9558 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9560 if(rsurface.texture && rsurface.texture->currentskinframe)
9562 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9563 c[3] *= rsurface.texture->currentalpha;
9573 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9575 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9576 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9577 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9580 // brighten it up (as texture value 127 means "unlit")
9581 c[0] *= 2 * r_refdef.view.colorscale;
9582 c[1] *= 2 * r_refdef.view.colorscale;
9583 c[2] *= 2 * r_refdef.view.colorscale;
9585 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9586 c[3] *= r_wateralpha.value;
9588 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9590 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9591 GL_DepthMask(false);
9593 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9595 GL_BlendFunc(GL_ONE, GL_ONE);
9596 GL_DepthMask(false);
9598 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9600 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9601 GL_DepthMask(false);
9603 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9605 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9606 GL_DepthMask(false);
9610 GL_BlendFunc(GL_ONE, GL_ZERO);
9611 GL_DepthMask(writedepth);
9614 if (r_showsurfaces.integer == 3)
9616 rsurface.passcolor4f = NULL;
9618 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9620 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9622 rsurface.passcolor4f = NULL;
9623 rsurface.passcolor4f_vertexbuffer = 0;
9624 rsurface.passcolor4f_bufferoffset = 0;
9626 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9628 qboolean applycolor = true;
9631 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9633 r_refdef.lightmapintensity = 1;
9634 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9635 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9637 else if (FAKELIGHT_ENABLED)
9639 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9641 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9642 RSurf_DrawBatch_GL11_ApplyFakeLight();
9643 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9647 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9649 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9650 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9651 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9654 if(!rsurface.passcolor4f)
9655 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9657 RSurf_DrawBatch_GL11_ApplyAmbient();
9658 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9659 if(r_refdef.fogenabled)
9660 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9661 RSurf_DrawBatch_GL11_ClampColor();
9663 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9664 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9667 else if (!r_refdef.view.showdebug)
9669 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9670 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9671 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9673 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9674 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9676 R_Mesh_PrepareVertices_Generic_Unlock();
9679 else if (r_showsurfaces.integer == 4)
9681 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9682 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9683 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9685 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9686 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9687 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9689 R_Mesh_PrepareVertices_Generic_Unlock();
9692 else if (r_showsurfaces.integer == 2)
9695 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9696 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9697 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9699 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9700 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9701 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9702 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9703 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9704 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9705 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9707 R_Mesh_PrepareVertices_Generic_Unlock();
9708 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9712 int texturesurfaceindex;
9714 const msurface_t *surface;
9715 float surfacecolor4f[4];
9716 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9717 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9719 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9721 surface = texturesurfacelist[texturesurfaceindex];
9722 k = (int)(((size_t)surface) / sizeof(msurface_t));
9723 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9724 for (j = 0;j < surface->num_vertices;j++)
9726 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9727 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9731 R_Mesh_PrepareVertices_Generic_Unlock();
9736 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9739 RSurf_SetupDepthAndCulling();
9740 if (r_showsurfaces.integer)
9742 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9745 switch (vid.renderpath)
9747 case RENDERPATH_GL20:
9748 case RENDERPATH_D3D9:
9749 case RENDERPATH_D3D10:
9750 case RENDERPATH_D3D11:
9751 case RENDERPATH_SOFT:
9752 case RENDERPATH_GLES2:
9753 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9755 case RENDERPATH_GL13:
9756 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9758 case RENDERPATH_GL11:
9759 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9765 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9768 RSurf_SetupDepthAndCulling();
9769 if (r_showsurfaces.integer)
9771 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9774 switch (vid.renderpath)
9776 case RENDERPATH_GL20:
9777 case RENDERPATH_D3D9:
9778 case RENDERPATH_D3D10:
9779 case RENDERPATH_D3D11:
9780 case RENDERPATH_SOFT:
9781 case RENDERPATH_GLES2:
9782 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9784 case RENDERPATH_GL13:
9785 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9787 case RENDERPATH_GL11:
9788 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9794 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9797 int texturenumsurfaces, endsurface;
9799 const msurface_t *surface;
9800 #define MAXBATCH_TRANSPARENTSURFACES 256
9801 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9803 // if the model is static it doesn't matter what value we give for
9804 // wantnormals and wanttangents, so this logic uses only rules applicable
9805 // to a model, knowing that they are meaningless otherwise
9806 if (ent == r_refdef.scene.worldentity)
9807 RSurf_ActiveWorldEntity();
9808 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9809 RSurf_ActiveModelEntity(ent, false, false, false);
9812 switch (vid.renderpath)
9814 case RENDERPATH_GL20:
9815 case RENDERPATH_D3D9:
9816 case RENDERPATH_D3D10:
9817 case RENDERPATH_D3D11:
9818 case RENDERPATH_SOFT:
9819 case RENDERPATH_GLES2:
9820 RSurf_ActiveModelEntity(ent, true, true, false);
9822 case RENDERPATH_GL13:
9823 case RENDERPATH_GL11:
9824 RSurf_ActiveModelEntity(ent, true, false, false);
9829 if (r_transparentdepthmasking.integer)
9831 qboolean setup = false;
9832 for (i = 0;i < numsurfaces;i = j)
9835 surface = rsurface.modelsurfaces + surfacelist[i];
9836 texture = surface->texture;
9837 rsurface.texture = R_GetCurrentTexture(texture);
9838 rsurface.lightmaptexture = NULL;
9839 rsurface.deluxemaptexture = NULL;
9840 rsurface.uselightmaptexture = false;
9841 // scan ahead until we find a different texture
9842 endsurface = min(i + 1024, numsurfaces);
9843 texturenumsurfaces = 0;
9844 texturesurfacelist[texturenumsurfaces++] = surface;
9845 for (;j < endsurface;j++)
9847 surface = rsurface.modelsurfaces + surfacelist[j];
9848 if (texture != surface->texture)
9850 texturesurfacelist[texturenumsurfaces++] = surface;
9852 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9854 // render the range of surfaces as depth
9858 GL_ColorMask(0,0,0,0);
9861 GL_BlendFunc(GL_ONE, GL_ZERO);
9863 // R_Mesh_ResetTextureState();
9864 R_SetupShader_DepthOrShadow();
9866 RSurf_SetupDepthAndCulling();
9867 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9868 if (rsurface.batchvertex3fbuffer)
9869 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9871 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9875 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9878 for (i = 0;i < numsurfaces;i = j)
9881 surface = rsurface.modelsurfaces + surfacelist[i];
9882 texture = surface->texture;
9883 rsurface.texture = R_GetCurrentTexture(texture);
9884 // scan ahead until we find a different texture
9885 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9886 texturenumsurfaces = 0;
9887 texturesurfacelist[texturenumsurfaces++] = surface;
9888 if(FAKELIGHT_ENABLED)
9890 rsurface.lightmaptexture = NULL;
9891 rsurface.deluxemaptexture = NULL;
9892 rsurface.uselightmaptexture = false;
9893 for (;j < endsurface;j++)
9895 surface = rsurface.modelsurfaces + surfacelist[j];
9896 if (texture != surface->texture)
9898 texturesurfacelist[texturenumsurfaces++] = surface;
9903 rsurface.lightmaptexture = surface->lightmaptexture;
9904 rsurface.deluxemaptexture = surface->deluxemaptexture;
9905 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9906 for (;j < endsurface;j++)
9908 surface = rsurface.modelsurfaces + surfacelist[j];
9909 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9911 texturesurfacelist[texturenumsurfaces++] = surface;
9914 // render the range of surfaces
9915 if (ent == r_refdef.scene.worldentity)
9916 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9918 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9920 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9923 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9925 // transparent surfaces get pushed off into the transparent queue
9926 int surfacelistindex;
9927 const msurface_t *surface;
9928 vec3_t tempcenter, center;
9929 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9931 surface = texturesurfacelist[surfacelistindex];
9932 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9933 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9934 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9935 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9936 if (queueentity->transparent_offset) // transparent offset
9938 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9939 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9940 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9942 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9946 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9948 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9950 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9952 RSurf_SetupDepthAndCulling();
9953 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9954 if (rsurface.batchvertex3fbuffer)
9955 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9957 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9961 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9963 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9966 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9969 if (!rsurface.texture->currentnumlayers)
9971 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9972 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9974 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9976 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9977 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9978 else if (!rsurface.texture->currentnumlayers)
9980 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9982 // in the deferred case, transparent surfaces were queued during prepass
9983 if (!r_shadow_usingdeferredprepass)
9984 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9988 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9989 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9994 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9998 R_FrameData_SetMark();
9999 // break the surface list down into batches by texture and use of lightmapping
10000 for (i = 0;i < numsurfaces;i = j)
10003 // texture is the base texture pointer, rsurface.texture is the
10004 // current frame/skin the texture is directing us to use (for example
10005 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10006 // use skin 1 instead)
10007 texture = surfacelist[i]->texture;
10008 rsurface.texture = R_GetCurrentTexture(texture);
10009 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10011 // if this texture is not the kind we want, skip ahead to the next one
10012 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10016 if(FAKELIGHT_ENABLED || depthonly || prepass)
10018 rsurface.lightmaptexture = NULL;
10019 rsurface.deluxemaptexture = NULL;
10020 rsurface.uselightmaptexture = false;
10021 // simply scan ahead until we find a different texture or lightmap state
10022 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10027 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10028 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10029 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10030 // simply scan ahead until we find a different texture or lightmap state
10031 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10034 // render the range of surfaces
10035 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10037 R_FrameData_ReturnToMark();
10040 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10044 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10047 if (!rsurface.texture->currentnumlayers)
10049 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10050 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10052 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10054 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10055 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10056 else if (!rsurface.texture->currentnumlayers)
10058 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10060 // in the deferred case, transparent surfaces were queued during prepass
10061 if (!r_shadow_usingdeferredprepass)
10062 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10066 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10067 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10072 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10075 texture_t *texture;
10076 R_FrameData_SetMark();
10077 // break the surface list down into batches by texture and use of lightmapping
10078 for (i = 0;i < numsurfaces;i = j)
10081 // texture is the base texture pointer, rsurface.texture is the
10082 // current frame/skin the texture is directing us to use (for example
10083 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10084 // use skin 1 instead)
10085 texture = surfacelist[i]->texture;
10086 rsurface.texture = R_GetCurrentTexture(texture);
10087 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10089 // if this texture is not the kind we want, skip ahead to the next one
10090 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10094 if(FAKELIGHT_ENABLED || depthonly || prepass)
10096 rsurface.lightmaptexture = NULL;
10097 rsurface.deluxemaptexture = NULL;
10098 rsurface.uselightmaptexture = false;
10099 // simply scan ahead until we find a different texture or lightmap state
10100 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10105 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10106 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10107 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10108 // simply scan ahead until we find a different texture or lightmap state
10109 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10112 // render the range of surfaces
10113 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10115 R_FrameData_ReturnToMark();
10118 float locboxvertex3f[6*4*3] =
10120 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10121 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10122 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10123 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10124 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10125 1,0,0, 0,0,0, 0,1,0, 1,1,0
10128 unsigned short locboxelements[6*2*3] =
10133 12,13,14, 12,14,15,
10134 16,17,18, 16,18,19,
10138 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10141 cl_locnode_t *loc = (cl_locnode_t *)ent;
10143 float vertex3f[6*4*3];
10145 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10146 GL_DepthMask(false);
10147 GL_DepthRange(0, 1);
10148 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10149 GL_DepthTest(true);
10150 GL_CullFace(GL_NONE);
10151 R_EntityMatrix(&identitymatrix);
10153 // R_Mesh_ResetTextureState();
10155 i = surfacelist[0];
10156 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10157 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10158 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10159 surfacelist[0] < 0 ? 0.5f : 0.125f);
10161 if (VectorCompare(loc->mins, loc->maxs))
10163 VectorSet(size, 2, 2, 2);
10164 VectorMA(loc->mins, -0.5f, size, mins);
10168 VectorCopy(loc->mins, mins);
10169 VectorSubtract(loc->maxs, loc->mins, size);
10172 for (i = 0;i < 6*4*3;)
10173 for (j = 0;j < 3;j++, i++)
10174 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10176 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10177 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10178 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10181 void R_DrawLocs(void)
10184 cl_locnode_t *loc, *nearestloc;
10186 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10187 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10189 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10190 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10194 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10196 if (decalsystem->decals)
10197 Mem_Free(decalsystem->decals);
10198 memset(decalsystem, 0, sizeof(*decalsystem));
10201 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)
10204 tridecal_t *decals;
10207 // expand or initialize the system
10208 if (decalsystem->maxdecals <= decalsystem->numdecals)
10210 decalsystem_t old = *decalsystem;
10211 qboolean useshortelements;
10212 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10213 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10214 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)));
10215 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10216 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10217 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10218 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10219 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10220 if (decalsystem->numdecals)
10221 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10223 Mem_Free(old.decals);
10224 for (i = 0;i < decalsystem->maxdecals*3;i++)
10225 decalsystem->element3i[i] = i;
10226 if (useshortelements)
10227 for (i = 0;i < decalsystem->maxdecals*3;i++)
10228 decalsystem->element3s[i] = i;
10231 // grab a decal and search for another free slot for the next one
10232 decals = decalsystem->decals;
10233 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10234 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10236 decalsystem->freedecal = i;
10237 if (decalsystem->numdecals <= i)
10238 decalsystem->numdecals = i + 1;
10240 // initialize the decal
10242 decal->triangleindex = triangleindex;
10243 decal->surfaceindex = surfaceindex;
10244 decal->decalsequence = decalsequence;
10245 decal->color4f[0][0] = c0[0];
10246 decal->color4f[0][1] = c0[1];
10247 decal->color4f[0][2] = c0[2];
10248 decal->color4f[0][3] = 1;
10249 decal->color4f[1][0] = c1[0];
10250 decal->color4f[1][1] = c1[1];
10251 decal->color4f[1][2] = c1[2];
10252 decal->color4f[1][3] = 1;
10253 decal->color4f[2][0] = c2[0];
10254 decal->color4f[2][1] = c2[1];
10255 decal->color4f[2][2] = c2[2];
10256 decal->color4f[2][3] = 1;
10257 decal->vertex3f[0][0] = v0[0];
10258 decal->vertex3f[0][1] = v0[1];
10259 decal->vertex3f[0][2] = v0[2];
10260 decal->vertex3f[1][0] = v1[0];
10261 decal->vertex3f[1][1] = v1[1];
10262 decal->vertex3f[1][2] = v1[2];
10263 decal->vertex3f[2][0] = v2[0];
10264 decal->vertex3f[2][1] = v2[1];
10265 decal->vertex3f[2][2] = v2[2];
10266 decal->texcoord2f[0][0] = t0[0];
10267 decal->texcoord2f[0][1] = t0[1];
10268 decal->texcoord2f[1][0] = t1[0];
10269 decal->texcoord2f[1][1] = t1[1];
10270 decal->texcoord2f[2][0] = t2[0];
10271 decal->texcoord2f[2][1] = t2[1];
10274 extern cvar_t cl_decals_bias;
10275 extern cvar_t cl_decals_models;
10276 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10277 // baseparms, parms, temps
10278 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)
10283 const float *vertex3f;
10284 const float *normal3f;
10286 float points[2][9][3];
10293 e = rsurface.modelelement3i + 3*triangleindex;
10295 vertex3f = rsurface.modelvertex3f;
10296 normal3f = rsurface.modelnormal3f;
10300 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10302 index = 3*e[cornerindex];
10303 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10308 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10310 index = 3*e[cornerindex];
10311 VectorCopy(vertex3f + index, v[cornerindex]);
10316 //TriangleNormal(v[0], v[1], v[2], normal);
10317 //if (DotProduct(normal, localnormal) < 0.0f)
10319 // clip by each of the box planes formed from the projection matrix
10320 // if anything survives, we emit the decal
10321 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]);
10324 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]);
10327 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]);
10330 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]);
10333 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]);
10336 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]);
10339 // some part of the triangle survived, so we have to accept it...
10342 // dynamic always uses the original triangle
10344 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10346 index = 3*e[cornerindex];
10347 VectorCopy(vertex3f + index, v[cornerindex]);
10350 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10352 // convert vertex positions to texcoords
10353 Matrix4x4_Transform(projection, v[cornerindex], temp);
10354 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10355 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10356 // calculate distance fade from the projection origin
10357 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10358 f = bound(0.0f, f, 1.0f);
10359 c[cornerindex][0] = r * f;
10360 c[cornerindex][1] = g * f;
10361 c[cornerindex][2] = b * f;
10362 c[cornerindex][3] = 1.0f;
10363 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10366 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);
10368 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10369 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);
10371 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)
10373 matrix4x4_t projection;
10374 decalsystem_t *decalsystem;
10377 const msurface_t *surface;
10378 const msurface_t *surfaces;
10379 const int *surfacelist;
10380 const texture_t *texture;
10382 int numsurfacelist;
10383 int surfacelistindex;
10386 float localorigin[3];
10387 float localnormal[3];
10388 float localmins[3];
10389 float localmaxs[3];
10392 float planes[6][4];
10395 int bih_triangles_count;
10396 int bih_triangles[256];
10397 int bih_surfaces[256];
10399 decalsystem = &ent->decalsystem;
10400 model = ent->model;
10401 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10403 R_DecalSystem_Reset(&ent->decalsystem);
10407 if (!model->brush.data_leafs && !cl_decals_models.integer)
10409 if (decalsystem->model)
10410 R_DecalSystem_Reset(decalsystem);
10414 if (decalsystem->model != model)
10415 R_DecalSystem_Reset(decalsystem);
10416 decalsystem->model = model;
10418 RSurf_ActiveModelEntity(ent, true, false, false);
10420 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10421 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10422 VectorNormalize(localnormal);
10423 localsize = worldsize*rsurface.inversematrixscale;
10424 localmins[0] = localorigin[0] - localsize;
10425 localmins[1] = localorigin[1] - localsize;
10426 localmins[2] = localorigin[2] - localsize;
10427 localmaxs[0] = localorigin[0] + localsize;
10428 localmaxs[1] = localorigin[1] + localsize;
10429 localmaxs[2] = localorigin[2] + localsize;
10431 //VectorCopy(localnormal, planes[4]);
10432 //VectorVectors(planes[4], planes[2], planes[0]);
10433 AnglesFromVectors(angles, localnormal, NULL, false);
10434 AngleVectors(angles, planes[0], planes[2], planes[4]);
10435 VectorNegate(planes[0], planes[1]);
10436 VectorNegate(planes[2], planes[3]);
10437 VectorNegate(planes[4], planes[5]);
10438 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10439 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10440 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10441 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10442 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10443 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10448 matrix4x4_t forwardprojection;
10449 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10450 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10455 float projectionvector[4][3];
10456 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10457 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10458 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10459 projectionvector[0][0] = planes[0][0] * ilocalsize;
10460 projectionvector[0][1] = planes[1][0] * ilocalsize;
10461 projectionvector[0][2] = planes[2][0] * ilocalsize;
10462 projectionvector[1][0] = planes[0][1] * ilocalsize;
10463 projectionvector[1][1] = planes[1][1] * ilocalsize;
10464 projectionvector[1][2] = planes[2][1] * ilocalsize;
10465 projectionvector[2][0] = planes[0][2] * ilocalsize;
10466 projectionvector[2][1] = planes[1][2] * ilocalsize;
10467 projectionvector[2][2] = planes[2][2] * ilocalsize;
10468 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10469 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10470 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10471 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10475 dynamic = model->surfmesh.isanimated;
10476 numsurfacelist = model->nummodelsurfaces;
10477 surfacelist = model->sortedmodelsurfaces;
10478 surfaces = model->data_surfaces;
10481 bih_triangles_count = -1;
10484 if(model->render_bih.numleafs)
10485 bih = &model->render_bih;
10486 else if(model->collision_bih.numleafs)
10487 bih = &model->collision_bih;
10490 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10491 if(bih_triangles_count == 0)
10493 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10495 if(bih_triangles_count > 0)
10497 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10499 surfaceindex = bih_surfaces[triangleindex];
10500 surface = surfaces + surfaceindex;
10501 texture = surface->texture;
10502 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10504 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10506 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10511 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10513 surfaceindex = surfacelist[surfacelistindex];
10514 surface = surfaces + surfaceindex;
10515 // check cull box first because it rejects more than any other check
10516 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10518 // skip transparent surfaces
10519 texture = surface->texture;
10520 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10522 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10524 numtriangles = surface->num_triangles;
10525 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10526 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10531 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10532 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)
10534 int renderentityindex;
10535 float worldmins[3];
10536 float worldmaxs[3];
10537 entity_render_t *ent;
10539 if (!cl_decals_newsystem.integer)
10542 worldmins[0] = worldorigin[0] - worldsize;
10543 worldmins[1] = worldorigin[1] - worldsize;
10544 worldmins[2] = worldorigin[2] - worldsize;
10545 worldmaxs[0] = worldorigin[0] + worldsize;
10546 worldmaxs[1] = worldorigin[1] + worldsize;
10547 worldmaxs[2] = worldorigin[2] + worldsize;
10549 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10551 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10553 ent = r_refdef.scene.entities[renderentityindex];
10554 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10557 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10561 typedef struct r_decalsystem_splatqueue_s
10563 vec3_t worldorigin;
10564 vec3_t worldnormal;
10570 r_decalsystem_splatqueue_t;
10572 int r_decalsystem_numqueued = 0;
10573 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10575 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)
10577 r_decalsystem_splatqueue_t *queue;
10579 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10582 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10583 VectorCopy(worldorigin, queue->worldorigin);
10584 VectorCopy(worldnormal, queue->worldnormal);
10585 Vector4Set(queue->color, r, g, b, a);
10586 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10587 queue->worldsize = worldsize;
10588 queue->decalsequence = cl.decalsequence++;
10591 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10594 r_decalsystem_splatqueue_t *queue;
10596 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10597 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);
10598 r_decalsystem_numqueued = 0;
10601 extern cvar_t cl_decals_max;
10602 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10605 decalsystem_t *decalsystem = &ent->decalsystem;
10612 if (!decalsystem->numdecals)
10615 if (r_showsurfaces.integer)
10618 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10620 R_DecalSystem_Reset(decalsystem);
10624 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10625 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10627 if (decalsystem->lastupdatetime)
10628 frametime = (cl.time - decalsystem->lastupdatetime);
10631 decalsystem->lastupdatetime = cl.time;
10632 decal = decalsystem->decals;
10633 numdecals = decalsystem->numdecals;
10635 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10637 if (decal->color4f[0][3])
10639 decal->lived += frametime;
10640 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10642 memset(decal, 0, sizeof(*decal));
10643 if (decalsystem->freedecal > i)
10644 decalsystem->freedecal = i;
10648 decal = decalsystem->decals;
10649 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10652 // collapse the array by shuffling the tail decals into the gaps
10655 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10656 decalsystem->freedecal++;
10657 if (decalsystem->freedecal == numdecals)
10659 decal[decalsystem->freedecal] = decal[--numdecals];
10662 decalsystem->numdecals = numdecals;
10664 if (numdecals <= 0)
10666 // if there are no decals left, reset decalsystem
10667 R_DecalSystem_Reset(decalsystem);
10671 extern skinframe_t *decalskinframe;
10672 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10675 decalsystem_t *decalsystem = &ent->decalsystem;
10684 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10687 numdecals = decalsystem->numdecals;
10691 if (r_showsurfaces.integer)
10694 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10696 R_DecalSystem_Reset(decalsystem);
10700 // if the model is static it doesn't matter what value we give for
10701 // wantnormals and wanttangents, so this logic uses only rules applicable
10702 // to a model, knowing that they are meaningless otherwise
10703 if (ent == r_refdef.scene.worldentity)
10704 RSurf_ActiveWorldEntity();
10706 RSurf_ActiveModelEntity(ent, false, false, false);
10708 decalsystem->lastupdatetime = cl.time;
10709 decal = decalsystem->decals;
10711 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10713 // update vertex positions for animated models
10714 v3f = decalsystem->vertex3f;
10715 c4f = decalsystem->color4f;
10716 t2f = decalsystem->texcoord2f;
10717 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10719 if (!decal->color4f[0][3])
10722 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10725 // update color values for fading decals
10726 if (decal->lived >= cl_decals_time.value)
10727 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10731 c4f[ 0] = decal->color4f[0][0] * alpha;
10732 c4f[ 1] = decal->color4f[0][1] * alpha;
10733 c4f[ 2] = decal->color4f[0][2] * alpha;
10735 c4f[ 4] = decal->color4f[1][0] * alpha;
10736 c4f[ 5] = decal->color4f[1][1] * alpha;
10737 c4f[ 6] = decal->color4f[1][2] * alpha;
10739 c4f[ 8] = decal->color4f[2][0] * alpha;
10740 c4f[ 9] = decal->color4f[2][1] * alpha;
10741 c4f[10] = decal->color4f[2][2] * alpha;
10744 t2f[0] = decal->texcoord2f[0][0];
10745 t2f[1] = decal->texcoord2f[0][1];
10746 t2f[2] = decal->texcoord2f[1][0];
10747 t2f[3] = decal->texcoord2f[1][1];
10748 t2f[4] = decal->texcoord2f[2][0];
10749 t2f[5] = decal->texcoord2f[2][1];
10751 // update vertex positions for animated models
10752 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10754 e = rsurface.modelelement3i + 3*decal->triangleindex;
10755 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10756 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10757 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10761 VectorCopy(decal->vertex3f[0], v3f);
10762 VectorCopy(decal->vertex3f[1], v3f + 3);
10763 VectorCopy(decal->vertex3f[2], v3f + 6);
10766 if (r_refdef.fogenabled)
10768 alpha = RSurf_FogVertex(v3f);
10769 VectorScale(c4f, alpha, c4f);
10770 alpha = RSurf_FogVertex(v3f + 3);
10771 VectorScale(c4f + 4, alpha, c4f + 4);
10772 alpha = RSurf_FogVertex(v3f + 6);
10773 VectorScale(c4f + 8, alpha, c4f + 8);
10784 r_refdef.stats.drawndecals += numtris;
10786 // now render the decals all at once
10787 // (this assumes they all use one particle font texture!)
10788 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);
10789 // R_Mesh_ResetTextureState();
10790 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10791 GL_DepthMask(false);
10792 GL_DepthRange(0, 1);
10793 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10794 GL_DepthTest(true);
10795 GL_CullFace(GL_NONE);
10796 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10797 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10798 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10802 static void R_DrawModelDecals(void)
10806 // fade faster when there are too many decals
10807 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10808 for (i = 0;i < r_refdef.scene.numentities;i++)
10809 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10811 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10812 for (i = 0;i < r_refdef.scene.numentities;i++)
10813 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10814 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10816 R_DecalSystem_ApplySplatEntitiesQueue();
10818 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10819 for (i = 0;i < r_refdef.scene.numentities;i++)
10820 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10822 r_refdef.stats.totaldecals += numdecals;
10824 if (r_showsurfaces.integer)
10827 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10829 for (i = 0;i < r_refdef.scene.numentities;i++)
10831 if (!r_refdef.viewcache.entityvisible[i])
10833 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10834 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10838 extern cvar_t mod_collision_bih;
10839 void R_DrawDebugModel(void)
10841 entity_render_t *ent = rsurface.entity;
10842 int i, j, k, l, flagsmask;
10843 const msurface_t *surface;
10844 dp_model_t *model = ent->model;
10847 switch(vid.renderpath)
10849 case RENDERPATH_GL11:
10850 case RENDERPATH_GL13:
10851 case RENDERPATH_GL20:
10853 case RENDERPATH_D3D9:
10854 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10856 case RENDERPATH_D3D10:
10857 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10859 case RENDERPATH_D3D11:
10860 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10862 case RENDERPATH_SOFT:
10863 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10865 case RENDERPATH_GLES2:
10866 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10870 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10872 // R_Mesh_ResetTextureState();
10873 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10874 GL_DepthRange(0, 1);
10875 GL_DepthTest(!r_showdisabledepthtest.integer);
10876 GL_DepthMask(false);
10877 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10879 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10883 qboolean cullbox = ent == r_refdef.scene.worldentity;
10884 const q3mbrush_t *brush;
10885 const bih_t *bih = &model->collision_bih;
10886 const bih_leaf_t *bihleaf;
10887 float vertex3f[3][3];
10888 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10890 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10892 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10894 switch (bihleaf->type)
10897 brush = model->brush.data_brushes + bihleaf->itemindex;
10898 if (brush->colbrushf && brush->colbrushf->numtriangles)
10900 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);
10901 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10902 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10905 case BIH_COLLISIONTRIANGLE:
10906 triangleindex = bihleaf->itemindex;
10907 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10908 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10909 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10910 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);
10911 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10912 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10914 case BIH_RENDERTRIANGLE:
10915 triangleindex = bihleaf->itemindex;
10916 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10917 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10918 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10919 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);
10920 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10921 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10927 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10929 if (r_showtris.integer || (r_shownormals.value != 0))
10931 if (r_showdisabledepthtest.integer)
10933 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10934 GL_DepthMask(false);
10938 GL_BlendFunc(GL_ONE, GL_ZERO);
10939 GL_DepthMask(true);
10941 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10943 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10945 rsurface.texture = R_GetCurrentTexture(surface->texture);
10946 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10948 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10949 if (r_showtris.value > 0)
10951 if (!rsurface.texture->currentlayers->depthmask)
10952 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10953 else if (ent == r_refdef.scene.worldentity)
10954 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10956 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10957 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10958 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10960 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10963 if (r_shownormals.value < 0)
10965 qglBegin(GL_LINES);
10966 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10968 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10969 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10970 qglVertex3f(v[0], v[1], v[2]);
10971 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10972 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10973 qglVertex3f(v[0], v[1], v[2]);
10978 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10980 qglBegin(GL_LINES);
10981 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10983 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10984 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10985 qglVertex3f(v[0], v[1], v[2]);
10986 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10987 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10988 qglVertex3f(v[0], v[1], v[2]);
10992 qglBegin(GL_LINES);
10993 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10995 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10996 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10997 qglVertex3f(v[0], v[1], v[2]);
10998 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10999 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11000 qglVertex3f(v[0], v[1], v[2]);
11004 qglBegin(GL_LINES);
11005 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11007 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11008 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11009 qglVertex3f(v[0], v[1], v[2]);
11010 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11011 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11012 qglVertex3f(v[0], v[1], v[2]);
11019 rsurface.texture = NULL;
11023 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11024 int r_maxsurfacelist = 0;
11025 const msurface_t **r_surfacelist = NULL;
11026 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11028 int i, j, endj, flagsmask;
11029 dp_model_t *model = r_refdef.scene.worldmodel;
11030 msurface_t *surfaces;
11031 unsigned char *update;
11032 int numsurfacelist = 0;
11036 if (r_maxsurfacelist < model->num_surfaces)
11038 r_maxsurfacelist = model->num_surfaces;
11040 Mem_Free((msurface_t**)r_surfacelist);
11041 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11044 RSurf_ActiveWorldEntity();
11046 surfaces = model->data_surfaces;
11047 update = model->brushq1.lightmapupdateflags;
11049 // update light styles on this submodel
11050 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11052 model_brush_lightstyleinfo_t *style;
11053 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11055 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11057 int *list = style->surfacelist;
11058 style->value = r_refdef.scene.lightstylevalue[style->style];
11059 for (j = 0;j < style->numsurfaces;j++)
11060 update[list[j]] = true;
11065 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11069 R_DrawDebugModel();
11070 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11074 rsurface.lightmaptexture = NULL;
11075 rsurface.deluxemaptexture = NULL;
11076 rsurface.uselightmaptexture = false;
11077 rsurface.texture = NULL;
11078 rsurface.rtlight = NULL;
11079 numsurfacelist = 0;
11080 // add visible surfaces to draw list
11081 for (i = 0;i < model->nummodelsurfaces;i++)
11083 j = model->sortedmodelsurfaces[i];
11084 if (r_refdef.viewcache.world_surfacevisible[j])
11085 r_surfacelist[numsurfacelist++] = surfaces + j;
11087 // update lightmaps if needed
11088 if (model->brushq1.firstrender)
11090 model->brushq1.firstrender = false;
11091 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11093 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11097 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11098 if (r_refdef.viewcache.world_surfacevisible[j])
11100 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11102 // don't do anything if there were no surfaces
11103 if (!numsurfacelist)
11105 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11108 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11110 // add to stats if desired
11111 if (r_speeds.integer && !skysurfaces && !depthonly)
11113 r_refdef.stats.world_surfaces += numsurfacelist;
11114 for (j = 0;j < numsurfacelist;j++)
11115 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11118 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11121 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11123 int i, j, endj, flagsmask;
11124 dp_model_t *model = ent->model;
11125 msurface_t *surfaces;
11126 unsigned char *update;
11127 int numsurfacelist = 0;
11131 if (r_maxsurfacelist < model->num_surfaces)
11133 r_maxsurfacelist = model->num_surfaces;
11135 Mem_Free((msurface_t **)r_surfacelist);
11136 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11139 // if the model is static it doesn't matter what value we give for
11140 // wantnormals and wanttangents, so this logic uses only rules applicable
11141 // to a model, knowing that they are meaningless otherwise
11142 if (ent == r_refdef.scene.worldentity)
11143 RSurf_ActiveWorldEntity();
11144 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11145 RSurf_ActiveModelEntity(ent, false, false, false);
11147 RSurf_ActiveModelEntity(ent, true, true, true);
11148 else if (depthonly)
11150 switch (vid.renderpath)
11152 case RENDERPATH_GL20:
11153 case RENDERPATH_D3D9:
11154 case RENDERPATH_D3D10:
11155 case RENDERPATH_D3D11:
11156 case RENDERPATH_SOFT:
11157 case RENDERPATH_GLES2:
11158 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11160 case RENDERPATH_GL13:
11161 case RENDERPATH_GL11:
11162 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11168 switch (vid.renderpath)
11170 case RENDERPATH_GL20:
11171 case RENDERPATH_D3D9:
11172 case RENDERPATH_D3D10:
11173 case RENDERPATH_D3D11:
11174 case RENDERPATH_SOFT:
11175 case RENDERPATH_GLES2:
11176 RSurf_ActiveModelEntity(ent, true, true, false);
11178 case RENDERPATH_GL13:
11179 case RENDERPATH_GL11:
11180 RSurf_ActiveModelEntity(ent, true, false, false);
11185 surfaces = model->data_surfaces;
11186 update = model->brushq1.lightmapupdateflags;
11188 // update light styles
11189 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11191 model_brush_lightstyleinfo_t *style;
11192 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11194 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11196 int *list = style->surfacelist;
11197 style->value = r_refdef.scene.lightstylevalue[style->style];
11198 for (j = 0;j < style->numsurfaces;j++)
11199 update[list[j]] = true;
11204 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11208 R_DrawDebugModel();
11209 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11213 rsurface.lightmaptexture = NULL;
11214 rsurface.deluxemaptexture = NULL;
11215 rsurface.uselightmaptexture = false;
11216 rsurface.texture = NULL;
11217 rsurface.rtlight = NULL;
11218 numsurfacelist = 0;
11219 // add visible surfaces to draw list
11220 for (i = 0;i < model->nummodelsurfaces;i++)
11221 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11222 // don't do anything if there were no surfaces
11223 if (!numsurfacelist)
11225 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11228 // update lightmaps if needed
11232 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11237 R_BuildLightMap(ent, surfaces + j);
11242 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11244 R_BuildLightMap(ent, surfaces + j);
11245 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11247 // add to stats if desired
11248 if (r_speeds.integer && !skysurfaces && !depthonly)
11250 r_refdef.stats.entities_surfaces += numsurfacelist;
11251 for (j = 0;j < numsurfacelist;j++)
11252 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11255 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11258 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11260 static texture_t texture;
11261 static msurface_t surface;
11262 const msurface_t *surfacelist = &surface;
11264 // fake enough texture and surface state to render this geometry
11266 texture.update_lastrenderframe = -1; // regenerate this texture
11267 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11268 texture.currentskinframe = skinframe;
11269 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11270 texture.offsetmapping = OFFSETMAPPING_OFF;
11271 texture.offsetscale = 1;
11272 texture.specularscalemod = 1;
11273 texture.specularpowermod = 1;
11275 surface.texture = &texture;
11276 surface.num_triangles = numtriangles;
11277 surface.num_firsttriangle = firsttriangle;
11278 surface.num_vertices = numvertices;
11279 surface.num_firstvertex = firstvertex;
11282 rsurface.texture = R_GetCurrentTexture(surface.texture);
11283 rsurface.lightmaptexture = NULL;
11284 rsurface.deluxemaptexture = NULL;
11285 rsurface.uselightmaptexture = false;
11286 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11289 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)
11291 static msurface_t surface;
11292 const msurface_t *surfacelist = &surface;
11294 // fake enough texture and surface state to render this geometry
11295 surface.texture = texture;
11296 surface.num_triangles = numtriangles;
11297 surface.num_firsttriangle = firsttriangle;
11298 surface.num_vertices = numvertices;
11299 surface.num_firstvertex = firstvertex;
11302 rsurface.texture = R_GetCurrentTexture(surface.texture);
11303 rsurface.lightmaptexture = NULL;
11304 rsurface.deluxemaptexture = NULL;
11305 rsurface.uselightmaptexture = false;
11306 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);