2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
134 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
135 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
136 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
137 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
142 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
143 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
144 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
146 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
147 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
148 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
149 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
150 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
151 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
152 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
153 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
155 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)"};
156 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
157 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)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
159 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)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
161 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
162 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
172 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)"};
173 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
174 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"};
175 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
176 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
177 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
179 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
180 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
181 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
182 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
184 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
185 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
186 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
187 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
188 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
189 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
190 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
192 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
193 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
194 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
195 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)"};
196 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
197 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
198 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
200 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
201 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
203 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"};
205 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"};
207 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
209 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
210 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"};
211 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
212 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
213 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
214 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
215 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)"};
216 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
217 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
219 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
220 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"};
222 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."};
224 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)"};
226 extern cvar_t v_glslgamma;
228 extern qboolean v_flipped_state;
230 static struct r_bloomstate_s
235 int bloomwidth, bloomheight;
237 textype_t texturetype;
238 int viewfbo; // used to check if r_viewfbo cvar has changed
240 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
241 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
242 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
244 int screentexturewidth, screentextureheight;
245 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
247 int bloomtexturewidth, bloomtextureheight;
248 rtexture_t *texture_bloom;
250 // arrays for rendering the screen passes
251 float screentexcoord2f[8];
252 float bloomtexcoord2f[8];
253 float offsettexcoord2f[8];
255 r_viewport_t viewport;
259 r_waterstate_t r_waterstate;
261 /// shadow volume bsp struct with automatically growing nodes buffer
264 rtexture_t *r_texture_blanknormalmap;
265 rtexture_t *r_texture_white;
266 rtexture_t *r_texture_grey128;
267 rtexture_t *r_texture_black;
268 rtexture_t *r_texture_notexture;
269 rtexture_t *r_texture_whitecube;
270 rtexture_t *r_texture_normalizationcube;
271 rtexture_t *r_texture_fogattenuation;
272 rtexture_t *r_texture_fogheighttexture;
273 rtexture_t *r_texture_gammaramps;
274 unsigned int r_texture_gammaramps_serial;
275 //rtexture_t *r_texture_fogintensity;
276 rtexture_t *r_texture_reflectcube;
278 // TODO: hash lookups?
279 typedef struct cubemapinfo_s
286 int r_texture_numcubemaps;
287 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
289 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
290 unsigned int r_numqueries;
291 unsigned int r_maxqueries;
293 typedef struct r_qwskincache_s
295 char name[MAX_QPATH];
296 skinframe_t *skinframe;
300 static r_qwskincache_t *r_qwskincache;
301 static int r_qwskincache_size;
303 /// vertex coordinates for a quad that covers the screen exactly
304 extern const float r_screenvertex3f[12];
305 extern const float r_d3dscreenvertex3f[12];
306 const float r_screenvertex3f[12] =
313 const float r_d3dscreenvertex3f[12] =
321 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
324 for (i = 0;i < verts;i++)
335 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
338 for (i = 0;i < verts;i++)
348 // FIXME: move this to client?
351 if (gamemode == GAME_NEHAHRA)
353 Cvar_Set("gl_fogenable", "0");
354 Cvar_Set("gl_fogdensity", "0.2");
355 Cvar_Set("gl_fogred", "0.3");
356 Cvar_Set("gl_foggreen", "0.3");
357 Cvar_Set("gl_fogblue", "0.3");
359 r_refdef.fog_density = 0;
360 r_refdef.fog_red = 0;
361 r_refdef.fog_green = 0;
362 r_refdef.fog_blue = 0;
363 r_refdef.fog_alpha = 1;
364 r_refdef.fog_start = 0;
365 r_refdef.fog_end = 16384;
366 r_refdef.fog_height = 1<<30;
367 r_refdef.fog_fadedepth = 128;
368 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
371 static void R_BuildBlankTextures(void)
373 unsigned char data[4];
374 data[2] = 128; // normal X
375 data[1] = 128; // normal Y
376 data[0] = 255; // normal Z
377 data[3] = 128; // height
378 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
383 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 static void R_BuildNoTexture(void)
399 unsigned char pix[16][16][4];
400 // this makes a light grey/dark grey checkerboard texture
401 for (y = 0;y < 16;y++)
403 for (x = 0;x < 16;x++)
405 if ((y < 8) ^ (x < 8))
421 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
424 static void R_BuildWhiteCube(void)
426 unsigned char data[6*1*1*4];
427 memset(data, 255, sizeof(data));
428 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
431 static void R_BuildNormalizationCube(void)
435 vec_t s, t, intensity;
438 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
439 for (side = 0;side < 6;side++)
441 for (y = 0;y < NORMSIZE;y++)
443 for (x = 0;x < NORMSIZE;x++)
445 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
446 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
481 intensity = 127.0f / sqrt(DotProduct(v, v));
482 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
483 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
484 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
485 data[((side*64+y)*64+x)*4+3] = 255;
489 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
493 static void R_BuildFogTexture(void)
497 unsigned char data1[FOGWIDTH][4];
498 //unsigned char data2[FOGWIDTH][4];
501 r_refdef.fogmasktable_start = r_refdef.fog_start;
502 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
503 r_refdef.fogmasktable_range = r_refdef.fogrange;
504 r_refdef.fogmasktable_density = r_refdef.fog_density;
506 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
507 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
509 d = (x * r - r_refdef.fogmasktable_start);
510 if(developer_extra.integer)
511 Con_DPrintf("%f ", d);
513 if (r_fog_exp2.integer)
514 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
516 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
517 if(developer_extra.integer)
518 Con_DPrintf(" : %f ", alpha);
519 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
520 if(developer_extra.integer)
521 Con_DPrintf(" = %f\n", alpha);
522 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
525 for (x = 0;x < FOGWIDTH;x++)
527 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
532 //data2[x][0] = 255 - b;
533 //data2[x][1] = 255 - b;
534 //data2[x][2] = 255 - b;
537 if (r_texture_fogattenuation)
539 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
544 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
545 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
549 static void R_BuildFogHeightTexture(void)
551 unsigned char *inpixels;
559 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
560 if (r_refdef.fogheighttexturename[0])
561 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
564 r_refdef.fog_height_tablesize = 0;
565 if (r_texture_fogheighttexture)
566 R_FreeTexture(r_texture_fogheighttexture);
567 r_texture_fogheighttexture = NULL;
568 if (r_refdef.fog_height_table2d)
569 Mem_Free(r_refdef.fog_height_table2d);
570 r_refdef.fog_height_table2d = NULL;
571 if (r_refdef.fog_height_table1d)
572 Mem_Free(r_refdef.fog_height_table1d);
573 r_refdef.fog_height_table1d = NULL;
577 r_refdef.fog_height_tablesize = size;
578 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
579 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
580 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
582 // LordHavoc: now the magic - what is that table2d for? it is a cooked
583 // average fog color table accounting for every fog layer between a point
584 // and the camera. (Note: attenuation is handled separately!)
585 for (y = 0;y < size;y++)
587 for (x = 0;x < size;x++)
593 for (j = x;j <= y;j++)
595 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601 for (j = x;j >= y;j--)
603 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
608 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
610 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
611 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
614 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
617 //=======================================================================================================================================================
619 static const char *builtinshaderstring =
620 #include "shader_glsl.h"
623 const char *builtinhlslshaderstring =
624 #include "shader_hlsl.h"
627 char *glslshaderstring = NULL;
628 char *hlslshaderstring = NULL;
630 //=======================================================================================================================================================
632 typedef struct shaderpermutationinfo_s
637 shaderpermutationinfo_t;
639 typedef struct shadermodeinfo_s
641 const char *vertexfilename;
642 const char *geometryfilename;
643 const char *fragmentfilename;
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
652 {"#define USEDIFFUSE\n", " diffuse"},
653 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
654 {"#define USEVIEWTINT\n", " viewtint"},
655 {"#define USECOLORMAPPING\n", " colormapping"},
656 {"#define USESATURATION\n", " saturation"},
657 {"#define USEFOGINSIDE\n", " foginside"},
658 {"#define USEFOGOUTSIDE\n", " fogoutside"},
659 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
660 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
661 {"#define USEGAMMARAMPS\n", " gammaramps"},
662 {"#define USECUBEFILTER\n", " cubefilter"},
663 {"#define USEGLOW\n", " glow"},
664 {"#define USEBLOOM\n", " bloom"},
665 {"#define USESPECULAR\n", " specular"},
666 {"#define USEPOSTPROCESSING\n", " postprocessing"},
667 {"#define USEREFLECTION\n", " reflection"},
668 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
669 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
671 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
672 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
673 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
674 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
675 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
676 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
677 {"#define USEALPHAKILL\n", " alphakill"},
678 {"#define USEREFLECTCUBE\n", " reflectcube"},
679 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
680 {"#define USEBOUNCEGRID\n", " bouncegrid"},
681 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
705 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725 struct r_glsl_permutation_s;
726 typedef struct r_glsl_permutation_s
729 struct r_glsl_permutation_s *hashnext;
731 unsigned int permutation;
733 /// indicates if we have tried compiling this permutation already
735 /// 0 if compilation failed
737 // texture units assigned to each detected uniform
738 int tex_Texture_First;
739 int tex_Texture_Second;
740 int tex_Texture_GammaRamps;
741 int tex_Texture_Normal;
742 int tex_Texture_Color;
743 int tex_Texture_Gloss;
744 int tex_Texture_Glow;
745 int tex_Texture_SecondaryNormal;
746 int tex_Texture_SecondaryColor;
747 int tex_Texture_SecondaryGloss;
748 int tex_Texture_SecondaryGlow;
749 int tex_Texture_Pants;
750 int tex_Texture_Shirt;
751 int tex_Texture_FogHeightTexture;
752 int tex_Texture_FogMask;
753 int tex_Texture_Lightmap;
754 int tex_Texture_Deluxemap;
755 int tex_Texture_Attenuation;
756 int tex_Texture_Cube;
757 int tex_Texture_Refraction;
758 int tex_Texture_Reflection;
759 int tex_Texture_ShadowMap2D;
760 int tex_Texture_CubeProjection;
761 int tex_Texture_ScreenDepth;
762 int tex_Texture_ScreenNormalMap;
763 int tex_Texture_ScreenDiffuse;
764 int tex_Texture_ScreenSpecular;
765 int tex_Texture_ReflectMask;
766 int tex_Texture_ReflectCube;
767 int tex_Texture_BounceGrid;
768 /// locations of detected uniforms in program object, or -1 if not found
769 int loc_Texture_First;
770 int loc_Texture_Second;
771 int loc_Texture_GammaRamps;
772 int loc_Texture_Normal;
773 int loc_Texture_Color;
774 int loc_Texture_Gloss;
775 int loc_Texture_Glow;
776 int loc_Texture_SecondaryNormal;
777 int loc_Texture_SecondaryColor;
778 int loc_Texture_SecondaryGloss;
779 int loc_Texture_SecondaryGlow;
780 int loc_Texture_Pants;
781 int loc_Texture_Shirt;
782 int loc_Texture_FogHeightTexture;
783 int loc_Texture_FogMask;
784 int loc_Texture_Lightmap;
785 int loc_Texture_Deluxemap;
786 int loc_Texture_Attenuation;
787 int loc_Texture_Cube;
788 int loc_Texture_Refraction;
789 int loc_Texture_Reflection;
790 int loc_Texture_ShadowMap2D;
791 int loc_Texture_CubeProjection;
792 int loc_Texture_ScreenDepth;
793 int loc_Texture_ScreenNormalMap;
794 int loc_Texture_ScreenDiffuse;
795 int loc_Texture_ScreenSpecular;
796 int loc_Texture_ReflectMask;
797 int loc_Texture_ReflectCube;
798 int loc_Texture_BounceGrid;
800 int loc_BloomBlur_Parameters;
802 int loc_Color_Ambient;
803 int loc_Color_Diffuse;
804 int loc_Color_Specular;
808 int loc_DeferredColor_Ambient;
809 int loc_DeferredColor_Diffuse;
810 int loc_DeferredColor_Specular;
811 int loc_DeferredMod_Diffuse;
812 int loc_DeferredMod_Specular;
813 int loc_DistortScaleRefractReflect;
816 int loc_FogHeightFade;
818 int loc_FogPlaneViewDist;
819 int loc_FogRangeRecip;
822 int loc_LightPosition;
823 int loc_OffsetMapping_ScaleSteps;
825 int loc_ReflectColor;
826 int loc_ReflectFactor;
827 int loc_ReflectOffset;
828 int loc_RefractColor;
830 int loc_ScreenCenterRefractReflect;
831 int loc_ScreenScaleRefractReflect;
832 int loc_ScreenToDepth;
833 int loc_ShadowMap_Parameters;
834 int loc_ShadowMap_TextureScale;
835 int loc_SpecularPower;
840 int loc_ViewTintColor;
842 int loc_ModelToLight;
844 int loc_BackgroundTexMatrix;
845 int loc_ModelViewProjectionMatrix;
846 int loc_ModelViewMatrix;
847 int loc_PixelToScreenTexCoord;
848 int loc_ModelToReflectCube;
849 int loc_ShadowMapMatrix;
850 int loc_BloomColorSubtract;
851 int loc_NormalmapScrollBlend;
852 int loc_BounceGridMatrix;
853 int loc_BounceGridIntensity;
855 r_glsl_permutation_t;
857 #define SHADERPERMUTATION_HASHSIZE 256
860 // non-degradable "lightweight" shader parameters to keep the permutations simpler
861 // these can NOT degrade! only use for simple stuff
864 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
865 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
866 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
867 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
868 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
869 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
870 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
872 #define SHADERSTATICPARMS_COUNT 7
874 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
875 static int shaderstaticparms_count = 0;
877 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
878 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
879 qboolean R_CompileShader_CheckStaticParms(void)
881 static int r_compileshader_staticparms_save[1];
882 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
883 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
886 if (r_glsl_saturation_redcompensate.integer)
887 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
888 if (r_glsl_vertextextureblend_usebothalphas.integer)
889 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
890 if (r_shadow_glossexact.integer)
891 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
892 if (r_glsl_postprocess.integer)
894 if (r_glsl_postprocess_uservec1_enable.integer)
895 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
896 if (r_glsl_postprocess_uservec2_enable.integer)
897 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
898 if (r_glsl_postprocess_uservec3_enable.integer)
899 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
900 if (r_glsl_postprocess_uservec4_enable.integer)
901 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
903 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
906 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
907 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
908 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
910 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
911 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
913 shaderstaticparms_count = 0;
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
922 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
925 /// information about each possible shader permutation
926 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
927 /// currently selected permutation
928 r_glsl_permutation_t *r_glsl_permutation;
929 /// storage for permutations linked in the hash table
930 memexpandablearray_t r_glsl_permutationarray;
932 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
934 //unsigned int hashdepth = 0;
935 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
936 r_glsl_permutation_t *p;
937 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
939 if (p->mode == mode && p->permutation == permutation)
941 //if (hashdepth > 10)
942 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
947 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
949 p->permutation = permutation;
950 p->hashnext = r_glsl_permutationhash[mode][hashindex];
951 r_glsl_permutationhash[mode][hashindex] = p;
952 //if (hashdepth > 10)
953 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
957 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
960 if (!filename || !filename[0])
962 if (!strcmp(filename, "glsl/default.glsl"))
964 if (!glslshaderstring)
966 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
967 if (glslshaderstring)
968 Con_DPrintf("Loading shaders from file %s...\n", filename);
970 glslshaderstring = (char *)builtinshaderstring;
972 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
973 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
976 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979 if (printfromdisknotice)
980 Con_DPrintf("from disk %s... ", filename);
986 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
990 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
991 char *vertexstring, *geometrystring, *fragmentstring;
992 char permutationname[256];
993 int vertstrings_count = 0;
994 int geomstrings_count = 0;
995 int fragstrings_count = 0;
996 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
998 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1005 permutationname[0] = 0;
1006 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1007 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1008 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1010 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1012 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1013 if(vid.support.gl20shaders130)
1015 vertstrings_list[vertstrings_count++] = "#version 130\n";
1016 geomstrings_list[geomstrings_count++] = "#version 130\n";
1017 fragstrings_list[fragstrings_count++] = "#version 130\n";
1018 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1019 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1020 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1023 // the first pretext is which type of shader to compile as
1024 // (later these will all be bound together as a program object)
1025 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1026 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1027 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1029 // the second pretext is the mode (for example a light source)
1030 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1031 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1032 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1033 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1035 // now add all the permutation pretexts
1036 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1038 if (permutation & (1<<i))
1040 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1041 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1042 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1043 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1047 // keep line numbers correct
1048 vertstrings_list[vertstrings_count++] = "\n";
1049 geomstrings_list[geomstrings_count++] = "\n";
1050 fragstrings_list[fragstrings_count++] = "\n";
1055 R_CompileShader_AddStaticParms(mode, permutation);
1056 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1057 vertstrings_count += shaderstaticparms_count;
1058 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059 geomstrings_count += shaderstaticparms_count;
1060 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061 fragstrings_count += shaderstaticparms_count;
1063 // now append the shader text itself
1064 vertstrings_list[vertstrings_count++] = vertexstring;
1065 geomstrings_list[geomstrings_count++] = geometrystring;
1066 fragstrings_list[fragstrings_count++] = fragmentstring;
1068 // if any sources were NULL, clear the respective list
1070 vertstrings_count = 0;
1071 if (!geometrystring)
1072 geomstrings_count = 0;
1073 if (!fragmentstring)
1074 fragstrings_count = 0;
1076 // compile the shader program
1077 if (vertstrings_count + geomstrings_count + fragstrings_count)
1078 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1082 qglUseProgram(p->program);CHECKGLERROR
1083 // look up all the uniform variable names we care about, so we don't
1084 // have to look them up every time we set them
1086 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1087 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1088 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1089 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1090 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1091 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1092 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1093 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1094 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1095 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1096 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1097 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1098 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1099 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1100 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1101 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1102 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1103 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1104 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1105 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1106 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1107 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1108 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1109 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1110 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1111 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1112 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1113 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1114 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1115 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1116 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1117 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1118 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1119 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1120 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1121 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1122 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1123 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1124 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1125 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1126 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1127 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1128 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1129 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1130 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1131 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1132 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1133 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1134 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1135 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1136 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1137 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1138 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1139 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1140 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1141 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1142 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1143 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1144 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1145 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1146 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1147 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1148 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1149 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1150 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1151 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1152 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1153 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1154 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1155 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1156 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1157 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1158 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1159 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1160 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1161 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1162 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1163 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1164 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1165 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1166 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1167 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1168 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1169 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1170 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1171 // initialize the samplers to refer to the texture units we use
1172 p->tex_Texture_First = -1;
1173 p->tex_Texture_Second = -1;
1174 p->tex_Texture_GammaRamps = -1;
1175 p->tex_Texture_Normal = -1;
1176 p->tex_Texture_Color = -1;
1177 p->tex_Texture_Gloss = -1;
1178 p->tex_Texture_Glow = -1;
1179 p->tex_Texture_SecondaryNormal = -1;
1180 p->tex_Texture_SecondaryColor = -1;
1181 p->tex_Texture_SecondaryGloss = -1;
1182 p->tex_Texture_SecondaryGlow = -1;
1183 p->tex_Texture_Pants = -1;
1184 p->tex_Texture_Shirt = -1;
1185 p->tex_Texture_FogHeightTexture = -1;
1186 p->tex_Texture_FogMask = -1;
1187 p->tex_Texture_Lightmap = -1;
1188 p->tex_Texture_Deluxemap = -1;
1189 p->tex_Texture_Attenuation = -1;
1190 p->tex_Texture_Cube = -1;
1191 p->tex_Texture_Refraction = -1;
1192 p->tex_Texture_Reflection = -1;
1193 p->tex_Texture_ShadowMap2D = -1;
1194 p->tex_Texture_CubeProjection = -1;
1195 p->tex_Texture_ScreenDepth = -1;
1196 p->tex_Texture_ScreenNormalMap = -1;
1197 p->tex_Texture_ScreenDiffuse = -1;
1198 p->tex_Texture_ScreenSpecular = -1;
1199 p->tex_Texture_ReflectMask = -1;
1200 p->tex_Texture_ReflectCube = -1;
1201 p->tex_Texture_BounceGrid = -1;
1203 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1204 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1205 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1206 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1207 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1208 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1209 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1211 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1212 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1213 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1214 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1215 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1216 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1217 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1218 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1219 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1220 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1221 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1222 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1223 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1224 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1225 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1227 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1228 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1229 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1230 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1231 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1232 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1234 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1237 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1241 Mem_Free(vertexstring);
1243 Mem_Free(geometrystring);
1245 Mem_Free(fragmentstring);
1248 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1250 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1251 if (r_glsl_permutation != perm)
1253 r_glsl_permutation = perm;
1254 if (!r_glsl_permutation->program)
1256 if (!r_glsl_permutation->compiled)
1257 R_GLSL_CompilePermutation(perm, mode, permutation);
1258 if (!r_glsl_permutation->program)
1260 // remove features until we find a valid permutation
1262 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1264 // reduce i more quickly whenever it would not remove any bits
1265 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1266 if (!(permutation & j))
1269 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270 if (!r_glsl_permutation->compiled)
1271 R_GLSL_CompilePermutation(perm, mode, permutation);
1272 if (r_glsl_permutation->program)
1275 if (i >= SHADERPERMUTATION_COUNT)
1277 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1278 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1279 qglUseProgram(0);CHECKGLERROR
1280 return; // no bit left to clear, entire mode is broken
1285 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1287 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1288 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1289 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1296 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1297 extern D3DCAPS9 vid_d3d9caps;
1300 struct r_hlsl_permutation_s;
1301 typedef struct r_hlsl_permutation_s
1303 /// hash lookup data
1304 struct r_hlsl_permutation_s *hashnext;
1306 unsigned int permutation;
1308 /// indicates if we have tried compiling this permutation already
1310 /// NULL if compilation failed
1311 IDirect3DVertexShader9 *vertexshader;
1312 IDirect3DPixelShader9 *pixelshader;
1314 r_hlsl_permutation_t;
1316 typedef enum D3DVSREGISTER_e
1318 D3DVSREGISTER_TexMatrix = 0, // float4x4
1319 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1320 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1321 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1322 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1323 D3DVSREGISTER_ModelToLight = 20, // float4x4
1324 D3DVSREGISTER_EyePosition = 24,
1325 D3DVSREGISTER_FogPlane = 25,
1326 D3DVSREGISTER_LightDir = 26,
1327 D3DVSREGISTER_LightPosition = 27,
1331 typedef enum D3DPSREGISTER_e
1333 D3DPSREGISTER_Alpha = 0,
1334 D3DPSREGISTER_BloomBlur_Parameters = 1,
1335 D3DPSREGISTER_ClientTime = 2,
1336 D3DPSREGISTER_Color_Ambient = 3,
1337 D3DPSREGISTER_Color_Diffuse = 4,
1338 D3DPSREGISTER_Color_Specular = 5,
1339 D3DPSREGISTER_Color_Glow = 6,
1340 D3DPSREGISTER_Color_Pants = 7,
1341 D3DPSREGISTER_Color_Shirt = 8,
1342 D3DPSREGISTER_DeferredColor_Ambient = 9,
1343 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1344 D3DPSREGISTER_DeferredColor_Specular = 11,
1345 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1346 D3DPSREGISTER_DeferredMod_Specular = 13,
1347 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1348 D3DPSREGISTER_EyePosition = 15, // unused
1349 D3DPSREGISTER_FogColor = 16,
1350 D3DPSREGISTER_FogHeightFade = 17,
1351 D3DPSREGISTER_FogPlane = 18,
1352 D3DPSREGISTER_FogPlaneViewDist = 19,
1353 D3DPSREGISTER_FogRangeRecip = 20,
1354 D3DPSREGISTER_LightColor = 21,
1355 D3DPSREGISTER_LightDir = 22, // unused
1356 D3DPSREGISTER_LightPosition = 23,
1357 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1358 D3DPSREGISTER_PixelSize = 25,
1359 D3DPSREGISTER_ReflectColor = 26,
1360 D3DPSREGISTER_ReflectFactor = 27,
1361 D3DPSREGISTER_ReflectOffset = 28,
1362 D3DPSREGISTER_RefractColor = 29,
1363 D3DPSREGISTER_Saturation = 30,
1364 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1365 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1366 D3DPSREGISTER_ScreenToDepth = 33,
1367 D3DPSREGISTER_ShadowMap_Parameters = 34,
1368 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1369 D3DPSREGISTER_SpecularPower = 36,
1370 D3DPSREGISTER_UserVec1 = 37,
1371 D3DPSREGISTER_UserVec2 = 38,
1372 D3DPSREGISTER_UserVec3 = 39,
1373 D3DPSREGISTER_UserVec4 = 40,
1374 D3DPSREGISTER_ViewTintColor = 41,
1375 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1376 D3DPSREGISTER_BloomColorSubtract = 43,
1377 D3DPSREGISTER_ViewToLight = 44, // float4x4
1378 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1379 D3DPSREGISTER_NormalmapScrollBlend = 52,
1384 /// information about each possible shader permutation
1385 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1386 /// currently selected permutation
1387 r_hlsl_permutation_t *r_hlsl_permutation;
1388 /// storage for permutations linked in the hash table
1389 memexpandablearray_t r_hlsl_permutationarray;
1391 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1393 //unsigned int hashdepth = 0;
1394 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1395 r_hlsl_permutation_t *p;
1396 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1398 if (p->mode == mode && p->permutation == permutation)
1400 //if (hashdepth > 10)
1401 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1406 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1408 p->permutation = permutation;
1409 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1410 r_hlsl_permutationhash[mode][hashindex] = p;
1411 //if (hashdepth > 10)
1412 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1419 if (!filename || !filename[0])
1421 if (!strcmp(filename, "hlsl/default.hlsl"))
1423 if (!hlslshaderstring)
1425 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1426 if (hlslshaderstring)
1427 Con_DPrintf("Loading shaders from file %s...\n", filename);
1429 hlslshaderstring = (char *)builtinhlslshaderstring;
1431 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1432 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1433 return shaderstring;
1435 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1438 if (printfromdisknotice)
1439 Con_DPrintf("from disk %s... ", filename);
1440 return shaderstring;
1442 return shaderstring;
1446 //#include <d3dx9shader.h>
1447 //#include <d3dx9mesh.h>
1449 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1451 DWORD *vsbin = NULL;
1452 DWORD *psbin = NULL;
1453 fs_offset_t vsbinsize;
1454 fs_offset_t psbinsize;
1455 // IDirect3DVertexShader9 *vs = NULL;
1456 // IDirect3DPixelShader9 *ps = NULL;
1457 ID3DXBuffer *vslog = NULL;
1458 ID3DXBuffer *vsbuffer = NULL;
1459 ID3DXConstantTable *vsconstanttable = NULL;
1460 ID3DXBuffer *pslog = NULL;
1461 ID3DXBuffer *psbuffer = NULL;
1462 ID3DXConstantTable *psconstanttable = NULL;
1465 char temp[MAX_INPUTLINE];
1466 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1467 qboolean debugshader = gl_paranoid.integer != 0;
1468 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1473 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1475 if ((!vsbin && vertstring) || (!psbin && fragstring))
1477 const char* dllnames_d3dx9 [] =
1501 dllhandle_t d3dx9_dll = NULL;
1502 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1503 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1504 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1505 dllfunction_t d3dx9_dllfuncs[] =
1507 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1508 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1509 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1512 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1514 DWORD shaderflags = 0;
1516 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1517 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1518 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1519 if (vertstring && vertstring[0])
1523 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1524 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1525 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1526 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1532 vsbinsize = vsbuffer->GetBufferSize();
1533 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1534 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1535 vsbuffer->Release();
1539 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1540 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1544 if (fragstring && fragstring[0])
1548 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1549 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1550 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1551 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1557 psbinsize = psbuffer->GetBufferSize();
1558 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1559 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1560 psbuffer->Release();
1564 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1565 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1569 Sys_UnloadLibrary(&d3dx9_dll);
1572 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1576 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1577 if (FAILED(vsresult))
1578 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1579 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1580 if (FAILED(psresult))
1581 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1583 // free the shader data
1584 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1585 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1588 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1591 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1592 int vertstring_length = 0;
1593 int geomstring_length = 0;
1594 int fragstring_length = 0;
1596 char *vertexstring, *geometrystring, *fragmentstring;
1597 char *vertstring, *geomstring, *fragstring;
1598 char permutationname[256];
1599 char cachename[256];
1600 int vertstrings_count = 0;
1601 int geomstrings_count = 0;
1602 int fragstrings_count = 0;
1603 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1605 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1610 p->vertexshader = NULL;
1611 p->pixelshader = NULL;
1613 permutationname[0] = 0;
1615 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1616 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1617 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1619 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1620 strlcat(cachename, "hlsl/", sizeof(cachename));
1622 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1623 vertstrings_count = 0;
1624 geomstrings_count = 0;
1625 fragstrings_count = 0;
1626 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1627 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1628 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1630 // the first pretext is which type of shader to compile as
1631 // (later these will all be bound together as a program object)
1632 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1633 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1634 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1636 // the second pretext is the mode (for example a light source)
1637 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1638 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1639 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1640 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1641 strlcat(cachename, modeinfo->name, sizeof(cachename));
1643 // now add all the permutation pretexts
1644 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1646 if (permutation & (1<<i))
1648 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1649 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1650 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1651 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1652 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1656 // keep line numbers correct
1657 vertstrings_list[vertstrings_count++] = "\n";
1658 geomstrings_list[geomstrings_count++] = "\n";
1659 fragstrings_list[fragstrings_count++] = "\n";
1664 R_CompileShader_AddStaticParms(mode, permutation);
1665 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1666 vertstrings_count += shaderstaticparms_count;
1667 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668 geomstrings_count += shaderstaticparms_count;
1669 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670 fragstrings_count += shaderstaticparms_count;
1672 // replace spaces in the cachename with _ characters
1673 for (i = 0;cachename[i];i++)
1674 if (cachename[i] == ' ')
1677 // now append the shader text itself
1678 vertstrings_list[vertstrings_count++] = vertexstring;
1679 geomstrings_list[geomstrings_count++] = geometrystring;
1680 fragstrings_list[fragstrings_count++] = fragmentstring;
1682 // if any sources were NULL, clear the respective list
1684 vertstrings_count = 0;
1685 if (!geometrystring)
1686 geomstrings_count = 0;
1687 if (!fragmentstring)
1688 fragstrings_count = 0;
1690 vertstring_length = 0;
1691 for (i = 0;i < vertstrings_count;i++)
1692 vertstring_length += strlen(vertstrings_list[i]);
1693 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1694 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1695 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1697 geomstring_length = 0;
1698 for (i = 0;i < geomstrings_count;i++)
1699 geomstring_length += strlen(geomstrings_list[i]);
1700 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1701 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1702 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1704 fragstring_length = 0;
1705 for (i = 0;i < fragstrings_count;i++)
1706 fragstring_length += strlen(fragstrings_list[i]);
1707 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1708 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1709 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1711 // try to load the cached shader, or generate one
1712 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1714 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1715 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1717 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1721 Mem_Free(vertstring);
1723 Mem_Free(geomstring);
1725 Mem_Free(fragstring);
1727 Mem_Free(vertexstring);
1729 Mem_Free(geometrystring);
1731 Mem_Free(fragmentstring);
1734 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1735 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1736 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);}
1737 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);}
1738 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);}
1739 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);}
1741 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1742 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1743 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);}
1744 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);}
1745 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);}
1746 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);}
1748 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1750 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1751 if (r_hlsl_permutation != perm)
1753 r_hlsl_permutation = perm;
1754 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756 if (!r_hlsl_permutation->compiled)
1757 R_HLSL_CompilePermutation(perm, mode, permutation);
1758 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1760 // remove features until we find a valid permutation
1762 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1764 // reduce i more quickly whenever it would not remove any bits
1765 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1766 if (!(permutation & j))
1769 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770 if (!r_hlsl_permutation->compiled)
1771 R_HLSL_CompilePermutation(perm, mode, permutation);
1772 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1775 if (i >= SHADERPERMUTATION_COUNT)
1777 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1778 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1779 return; // no bit left to clear, entire mode is broken
1783 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1784 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1786 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1787 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1788 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1792 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1794 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1795 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1796 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1797 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1800 void R_GLSL_Restart_f(void)
1802 unsigned int i, limit;
1803 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1804 Mem_Free(glslshaderstring);
1805 glslshaderstring = NULL;
1806 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1807 Mem_Free(hlslshaderstring);
1808 hlslshaderstring = NULL;
1809 switch(vid.renderpath)
1811 case RENDERPATH_D3D9:
1814 r_hlsl_permutation_t *p;
1815 r_hlsl_permutation = NULL;
1816 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1817 for (i = 0;i < limit;i++)
1819 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1821 if (p->vertexshader)
1822 IDirect3DVertexShader9_Release(p->vertexshader);
1824 IDirect3DPixelShader9_Release(p->pixelshader);
1825 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1828 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1832 case RENDERPATH_D3D10:
1833 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835 case RENDERPATH_D3D11:
1836 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838 case RENDERPATH_GL20:
1839 case RENDERPATH_GLES2:
1841 r_glsl_permutation_t *p;
1842 r_glsl_permutation = NULL;
1843 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1844 for (i = 0;i < limit;i++)
1846 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1848 GL_Backend_FreeProgram(p->program);
1849 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1852 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1855 case RENDERPATH_GL13:
1856 case RENDERPATH_GL11:
1858 case RENDERPATH_SOFT:
1863 void R_GLSL_DumpShader_f(void)
1868 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1871 FS_Print(file, "/* The engine may define the following macros:\n");
1872 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1873 for (i = 0;i < SHADERMODE_COUNT;i++)
1874 FS_Print(file, glslshadermodeinfo[i].pretext);
1875 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1876 FS_Print(file, shaderpermutationinfo[i].pretext);
1877 FS_Print(file, "*/\n");
1878 FS_Print(file, builtinshaderstring);
1880 Con_Printf("glsl/default.glsl written\n");
1883 Con_Printf("failed to write to glsl/default.glsl\n");
1885 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1888 FS_Print(file, "/* The engine may define the following macros:\n");
1889 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1890 for (i = 0;i < SHADERMODE_COUNT;i++)
1891 FS_Print(file, hlslshadermodeinfo[i].pretext);
1892 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1893 FS_Print(file, shaderpermutationinfo[i].pretext);
1894 FS_Print(file, "*/\n");
1895 FS_Print(file, builtinhlslshaderstring);
1897 Con_Printf("hlsl/default.hlsl written\n");
1900 Con_Printf("failed to write to hlsl/default.hlsl\n");
1903 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1906 texturemode = GL_MODULATE;
1907 switch (vid.renderpath)
1909 case RENDERPATH_D3D9:
1911 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))));
1912 R_Mesh_TexBind(GL20TU_FIRST , first );
1913 R_Mesh_TexBind(GL20TU_SECOND, second);
1916 case RENDERPATH_D3D10:
1917 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919 case RENDERPATH_D3D11:
1920 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1922 case RENDERPATH_GL20:
1923 case RENDERPATH_GLES2:
1924 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))));
1925 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1926 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1928 case RENDERPATH_GL13:
1929 R_Mesh_TexBind(0, first );
1930 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1931 R_Mesh_TexBind(1, second);
1933 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1935 case RENDERPATH_GL11:
1936 R_Mesh_TexBind(0, first );
1938 case RENDERPATH_SOFT:
1939 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))));
1940 R_Mesh_TexBind(GL20TU_FIRST , first );
1941 R_Mesh_TexBind(GL20TU_SECOND, second);
1946 void R_SetupShader_DepthOrShadow(void)
1948 switch (vid.renderpath)
1950 case RENDERPATH_D3D9:
1952 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1955 case RENDERPATH_D3D10:
1956 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_D3D11:
1959 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_GL20:
1962 case RENDERPATH_GLES2:
1963 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1965 case RENDERPATH_GL13:
1966 R_Mesh_TexBind(0, 0);
1967 R_Mesh_TexBind(1, 0);
1969 case RENDERPATH_GL11:
1970 R_Mesh_TexBind(0, 0);
1972 case RENDERPATH_SOFT:
1973 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1978 void R_SetupShader_ShowDepth(void)
1980 switch (vid.renderpath)
1982 case RENDERPATH_D3D9:
1984 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1987 case RENDERPATH_D3D10:
1988 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990 case RENDERPATH_D3D11:
1991 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993 case RENDERPATH_GL20:
1994 case RENDERPATH_GLES2:
1995 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1997 case RENDERPATH_GL13:
1999 case RENDERPATH_GL11:
2001 case RENDERPATH_SOFT:
2002 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2007 extern qboolean r_shadow_usingdeferredprepass;
2008 extern cvar_t r_shadow_deferred_8bitrange;
2009 extern rtexture_t *r_shadow_attenuationgradienttexture;
2010 extern rtexture_t *r_shadow_attenuation2dtexture;
2011 extern rtexture_t *r_shadow_attenuation3dtexture;
2012 extern qboolean r_shadow_usingshadowmap2d;
2013 extern qboolean r_shadow_usingshadowmaportho;
2014 extern float r_shadow_shadowmap_texturescale[2];
2015 extern float r_shadow_shadowmap_parameters[4];
2016 extern qboolean r_shadow_shadowmapvsdct;
2017 extern qboolean r_shadow_shadowmapsampler;
2018 extern int r_shadow_shadowmappcf;
2019 extern rtexture_t *r_shadow_shadowmap2dtexture;
2020 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2021 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2022 extern matrix4x4_t r_shadow_shadowmapmatrix;
2023 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2024 extern int r_shadow_prepass_width;
2025 extern int r_shadow_prepass_height;
2026 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2027 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2028 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2029 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2030 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2032 #define BLENDFUNC_ALLOWS_COLORMOD 1
2033 #define BLENDFUNC_ALLOWS_FOG 2
2034 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2035 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2036 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2037 static int R_BlendFuncFlags(int src, int dst)
2041 // a blendfunc allows colormod if:
2042 // a) it can never keep the destination pixel invariant, or
2043 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2044 // this is to prevent unintended side effects from colormod
2046 // a blendfunc allows fog if:
2047 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2048 // this is to prevent unintended side effects from fog
2050 // these checks are the output of fogeval.pl
2052 r |= BLENDFUNC_ALLOWS_COLORMOD;
2053 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2054 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2055 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2056 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2057 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2061 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2062 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2063 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2064 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2065 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2066 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2067 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2068 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2070 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2071 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2072 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2073 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2078 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)
2080 // select a permutation of the lighting shader appropriate to this
2081 // combination of texture, entity, light source, and fogging, only use the
2082 // minimum features necessary to avoid wasting rendering time in the
2083 // fragment shader on features that are not being used
2084 unsigned int permutation = 0;
2085 unsigned int mode = 0;
2087 static float dummy_colormod[3] = {1, 1, 1};
2088 float *colormod = rsurface.colormod;
2090 matrix4x4_t tempmatrix;
2091 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2092 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2093 permutation |= SHADERPERMUTATION_ALPHAKILL;
2094 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2095 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2096 if (rsurfacepass == RSURFPASS_BACKGROUND)
2098 // distorted background
2099 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2101 mode = SHADERMODE_WATER;
2102 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2104 // this is the right thing to do for wateralpha
2105 GL_BlendFunc(GL_ONE, GL_ZERO);
2106 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2110 // this is the right thing to do for entity alpha
2111 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2112 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2115 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2117 mode = SHADERMODE_REFRACTION;
2118 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2123 mode = SHADERMODE_GENERIC;
2124 permutation |= SHADERPERMUTATION_DIFFUSE;
2125 GL_BlendFunc(GL_ONE, GL_ZERO);
2126 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2129 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2131 if (r_glsl_offsetmapping.integer)
2133 switch(rsurface.texture->offsetmapping)
2135 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2136 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2137 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2138 case OFFSETMAPPING_OFF: break;
2141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143 // normalmap (deferred prepass), may use alpha test on diffuse
2144 mode = SHADERMODE_DEFERREDGEOMETRY;
2145 GL_BlendFunc(GL_ONE, GL_ZERO);
2146 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2148 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2150 if (r_glsl_offsetmapping.integer)
2152 switch(rsurface.texture->offsetmapping)
2154 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2155 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2156 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2157 case OFFSETMAPPING_OFF: break;
2160 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2161 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2163 mode = SHADERMODE_LIGHTSOURCE;
2164 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2165 permutation |= SHADERPERMUTATION_CUBEFILTER;
2166 if (diffusescale > 0)
2167 permutation |= SHADERPERMUTATION_DIFFUSE;
2168 if (specularscale > 0)
2169 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2170 if (r_refdef.fogenabled)
2171 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2172 if (rsurface.texture->colormapping)
2173 permutation |= SHADERPERMUTATION_COLORMAPPING;
2174 if (r_shadow_usingshadowmap2d)
2176 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2177 if(r_shadow_shadowmapvsdct)
2178 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2180 if (r_shadow_shadowmapsampler)
2181 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2182 if (r_shadow_shadowmappcf > 1)
2183 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2184 else if (r_shadow_shadowmappcf)
2185 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2187 if (rsurface.texture->reflectmasktexture)
2188 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2189 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2190 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2192 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2194 if (r_glsl_offsetmapping.integer)
2196 switch(rsurface.texture->offsetmapping)
2198 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2199 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201 case OFFSETMAPPING_OFF: break;
2204 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2205 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2206 // unshaded geometry (fullbright or ambient model lighting)
2207 mode = SHADERMODE_FLATCOLOR;
2208 ambientscale = diffusescale = specularscale = 0;
2209 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2210 permutation |= SHADERPERMUTATION_GLOW;
2211 if (r_refdef.fogenabled)
2212 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2213 if (rsurface.texture->colormapping)
2214 permutation |= SHADERPERMUTATION_COLORMAPPING;
2215 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2217 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2218 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2220 if (r_shadow_shadowmapsampler)
2221 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2222 if (r_shadow_shadowmappcf > 1)
2223 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2224 else if (r_shadow_shadowmappcf)
2225 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2227 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2228 permutation |= SHADERPERMUTATION_REFLECTION;
2229 if (rsurface.texture->reflectmasktexture)
2230 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2231 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2232 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2234 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2236 if (r_glsl_offsetmapping.integer)
2238 switch(rsurface.texture->offsetmapping)
2240 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2241 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243 case OFFSETMAPPING_OFF: break;
2246 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2247 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2248 // directional model lighting
2249 mode = SHADERMODE_LIGHTDIRECTION;
2250 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2251 permutation |= SHADERPERMUTATION_GLOW;
2252 permutation |= SHADERPERMUTATION_DIFFUSE;
2253 if (specularscale > 0)
2254 permutation |= SHADERPERMUTATION_SPECULAR;
2255 if (r_refdef.fogenabled)
2256 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2257 if (rsurface.texture->colormapping)
2258 permutation |= SHADERPERMUTATION_COLORMAPPING;
2259 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2261 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2262 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2264 if (r_shadow_shadowmapsampler)
2265 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2266 if (r_shadow_shadowmappcf > 1)
2267 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2268 else if (r_shadow_shadowmappcf)
2269 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2271 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2272 permutation |= SHADERPERMUTATION_REFLECTION;
2273 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2274 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2275 if (rsurface.texture->reflectmasktexture)
2276 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2277 if (r_shadow_bouncegridtexture)
2279 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2280 if (r_shadow_bouncegriddirectional)
2281 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2283 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2284 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2288 if (r_glsl_offsetmapping.integer)
2290 switch(rsurface.texture->offsetmapping)
2292 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2293 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295 case OFFSETMAPPING_OFF: break;
2298 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2299 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2300 // ambient model lighting
2301 mode = SHADERMODE_LIGHTDIRECTION;
2302 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2303 permutation |= SHADERPERMUTATION_GLOW;
2304 if (r_refdef.fogenabled)
2305 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2306 if (rsurface.texture->colormapping)
2307 permutation |= SHADERPERMUTATION_COLORMAPPING;
2308 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2311 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313 if (r_shadow_shadowmapsampler)
2314 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2315 if (r_shadow_shadowmappcf > 1)
2316 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2317 else if (r_shadow_shadowmappcf)
2318 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2320 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2321 permutation |= SHADERPERMUTATION_REFLECTION;
2322 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2323 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2324 if (rsurface.texture->reflectmasktexture)
2325 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2326 if (r_shadow_bouncegridtexture)
2328 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2329 if (r_shadow_bouncegriddirectional)
2330 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2332 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2337 if (r_glsl_offsetmapping.integer)
2339 switch(rsurface.texture->offsetmapping)
2341 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2342 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2343 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344 case OFFSETMAPPING_OFF: break;
2347 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2348 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2350 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2351 permutation |= SHADERPERMUTATION_GLOW;
2352 if (r_refdef.fogenabled)
2353 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2354 if (rsurface.texture->colormapping)
2355 permutation |= SHADERPERMUTATION_COLORMAPPING;
2356 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2358 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2359 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2361 if (r_shadow_shadowmapsampler)
2362 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2363 if (r_shadow_shadowmappcf > 1)
2364 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2365 else if (r_shadow_shadowmappcf)
2366 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2368 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2369 permutation |= SHADERPERMUTATION_REFLECTION;
2370 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2371 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2372 if (rsurface.texture->reflectmasktexture)
2373 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2374 if (FAKELIGHT_ENABLED)
2376 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2377 mode = SHADERMODE_FAKELIGHT;
2378 permutation |= SHADERPERMUTATION_DIFFUSE;
2379 if (specularscale > 0)
2380 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2382 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2384 // deluxemapping (light direction texture)
2385 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2386 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2388 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2389 permutation |= SHADERPERMUTATION_DIFFUSE;
2390 if (specularscale > 0)
2391 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2393 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2395 // fake deluxemapping (uniform light direction in tangentspace)
2396 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2397 permutation |= SHADERPERMUTATION_DIFFUSE;
2398 if (specularscale > 0)
2399 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2401 else if (rsurface.uselightmaptexture)
2403 // ordinary lightmapping (q1bsp, q3bsp)
2404 mode = SHADERMODE_LIGHTMAP;
2408 // ordinary vertex coloring (q3bsp)
2409 mode = SHADERMODE_VERTEXCOLOR;
2411 if (r_shadow_bouncegridtexture)
2413 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2414 if (r_shadow_bouncegriddirectional)
2415 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2417 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2418 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2421 colormod = dummy_colormod;
2422 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2423 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2424 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2425 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2426 switch(vid.renderpath)
2428 case RENDERPATH_D3D9:
2430 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);
2431 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2432 R_SetupShader_SetPermutationHLSL(mode, permutation);
2433 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2434 if (mode == SHADERMODE_LIGHTSOURCE)
2436 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2437 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2441 if (mode == SHADERMODE_LIGHTDIRECTION)
2443 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2446 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2447 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2448 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2449 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2450 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2452 if (mode == SHADERMODE_LIGHTSOURCE)
2454 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2455 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2456 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2457 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2458 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2460 // additive passes are only darkened by fog, not tinted
2461 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2462 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2466 if (mode == SHADERMODE_FLATCOLOR)
2468 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2470 else if (mode == SHADERMODE_LIGHTDIRECTION)
2472 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]);
2473 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2474 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);
2475 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);
2476 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2477 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2478 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2482 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2483 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2484 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);
2485 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);
2486 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2488 // additive passes are only darkened by fog, not tinted
2489 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2490 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2492 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2493 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);
2494 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2495 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2496 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2497 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2498 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2499 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2500 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2501 if (mode == SHADERMODE_WATER)
2502 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2504 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2505 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2506 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2507 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));
2508 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2509 if (rsurface.texture->pantstexture)
2510 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2512 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2513 if (rsurface.texture->shirttexture)
2514 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2516 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2517 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2518 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2519 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2520 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2521 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2522 r_glsl_offsetmapping_scale.value,
2523 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2524 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2525 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2527 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2528 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2530 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2531 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2532 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2533 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2534 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2535 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2536 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2537 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2538 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2539 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2540 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2541 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2542 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2543 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2544 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2545 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2546 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2547 if (rsurfacepass == RSURFPASS_BACKGROUND)
2549 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2550 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2551 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2555 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2557 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2558 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2559 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2560 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2561 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2563 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2564 if (rsurface.rtlight)
2566 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2567 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2572 case RENDERPATH_D3D10:
2573 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2575 case RENDERPATH_D3D11:
2576 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2578 case RENDERPATH_GL20:
2579 case RENDERPATH_GLES2:
2580 if (!vid.useinterleavedarrays)
2582 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);
2583 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2584 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2585 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2586 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2587 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2588 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2589 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2593 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);
2594 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2596 R_SetupShader_SetPermutationGLSL(mode, permutation);
2597 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2598 if (mode == SHADERMODE_LIGHTSOURCE)
2600 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2601 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2602 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2603 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2604 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2605 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);
2607 // additive passes are only darkened by fog, not tinted
2608 if (r_glsl_permutation->loc_FogColor >= 0)
2609 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2610 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2614 if (mode == SHADERMODE_FLATCOLOR)
2616 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2618 else if (mode == SHADERMODE_LIGHTDIRECTION)
2620 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]);
2621 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]);
2622 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);
2623 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);
2624 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);
2625 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]);
2626 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]);
2630 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]);
2631 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]);
2632 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);
2633 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);
2634 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);
2636 // additive passes are only darkened by fog, not tinted
2637 if (r_glsl_permutation->loc_FogColor >= 0)
2639 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2640 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2642 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2644 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);
2645 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]);
2646 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]);
2647 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]);
2648 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]);
2649 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2650 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2651 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2652 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]);
2654 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2655 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2656 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2657 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]);
2658 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]);
2660 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2661 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));
2662 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2663 if (r_glsl_permutation->loc_Color_Pants >= 0)
2665 if (rsurface.texture->pantstexture)
2666 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2668 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2670 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2672 if (rsurface.texture->shirttexture)
2673 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2675 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2677 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]);
2678 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2679 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2680 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2681 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2682 r_glsl_offsetmapping_scale.value,
2683 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2684 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2685 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2687 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]);
2688 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2689 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);}
2690 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2692 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2693 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2694 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2695 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2696 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2697 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2698 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2699 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2700 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2701 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2703 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2704 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2705 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2706 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);
2707 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2708 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2709 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2710 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2711 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2712 if (rsurfacepass == RSURFPASS_BACKGROUND)
2714 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);
2715 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);
2716 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);
2720 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);
2722 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2723 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2724 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2725 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2726 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2728 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2729 if (rsurface.rtlight)
2731 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2732 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2735 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2738 case RENDERPATH_GL13:
2739 case RENDERPATH_GL11:
2741 case RENDERPATH_SOFT:
2742 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);
2743 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2744 R_SetupShader_SetPermutationSoft(mode, permutation);
2745 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2746 if (mode == SHADERMODE_LIGHTSOURCE)
2748 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2749 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2750 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2751 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2755 // additive passes are only darkened by fog, not tinted
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2757 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2761 if (mode == SHADERMODE_FLATCOLOR)
2763 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2765 else if (mode == SHADERMODE_LIGHTDIRECTION)
2767 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]);
2768 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2769 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);
2770 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);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2772 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]);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2778 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2779 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);
2780 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);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2783 // additive passes are only darkened by fog, not tinted
2784 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2785 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2788 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);
2789 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2790 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2791 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]);
2792 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]);
2793 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2795 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2796 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2798 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2799 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2800 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2801 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2802 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]);
2804 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2805 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));
2806 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2807 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2809 if (rsurface.texture->pantstexture)
2810 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2812 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2814 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2816 if (rsurface.texture->shirttexture)
2817 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2819 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2821 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2822 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2823 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2824 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2825 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2826 r_glsl_offsetmapping_scale.value,
2827 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2828 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2829 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2831 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2832 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2834 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2835 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2836 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2837 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2838 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2839 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2840 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2841 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2842 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2843 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2844 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2845 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2846 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2847 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2848 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2849 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2850 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2851 if (rsurfacepass == RSURFPASS_BACKGROUND)
2853 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2854 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2855 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2859 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2861 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2862 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2863 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2864 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2865 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2867 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2868 if (rsurface.rtlight)
2870 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2871 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2878 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2880 // select a permutation of the lighting shader appropriate to this
2881 // combination of texture, entity, light source, and fogging, only use the
2882 // minimum features necessary to avoid wasting rendering time in the
2883 // fragment shader on features that are not being used
2884 unsigned int permutation = 0;
2885 unsigned int mode = 0;
2886 const float *lightcolorbase = rtlight->currentcolor;
2887 float ambientscale = rtlight->ambientscale;
2888 float diffusescale = rtlight->diffusescale;
2889 float specularscale = rtlight->specularscale;
2890 // this is the location of the light in view space
2891 vec3_t viewlightorigin;
2892 // this transforms from view space (camera) to light space (cubemap)
2893 matrix4x4_t viewtolight;
2894 matrix4x4_t lighttoview;
2895 float viewtolight16f[16];
2896 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2898 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2899 if (rtlight->currentcubemap != r_texture_whitecube)
2900 permutation |= SHADERPERMUTATION_CUBEFILTER;
2901 if (diffusescale > 0)
2902 permutation |= SHADERPERMUTATION_DIFFUSE;
2903 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2904 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2905 if (r_shadow_usingshadowmap2d)
2907 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2908 if (r_shadow_shadowmapvsdct)
2909 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2911 if (r_shadow_shadowmapsampler)
2912 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2913 if (r_shadow_shadowmappcf > 1)
2914 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2915 else if (r_shadow_shadowmappcf)
2916 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2918 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2919 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2920 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2921 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2922 switch(vid.renderpath)
2924 case RENDERPATH_D3D9:
2926 R_SetupShader_SetPermutationHLSL(mode, permutation);
2927 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2928 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2929 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2930 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2931 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2932 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2933 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2934 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2935 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2936 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2938 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2939 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2940 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2941 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2942 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2943 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2946 case RENDERPATH_D3D10:
2947 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2949 case RENDERPATH_D3D11:
2950 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2952 case RENDERPATH_GL20:
2953 case RENDERPATH_GLES2:
2954 R_SetupShader_SetPermutationGLSL(mode, permutation);
2955 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2956 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2957 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);
2958 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);
2959 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);
2960 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]);
2961 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]);
2962 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));
2963 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]);
2964 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2966 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2967 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2968 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2969 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2970 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2971 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2973 case RENDERPATH_GL13:
2974 case RENDERPATH_GL11:
2976 case RENDERPATH_SOFT:
2977 R_SetupShader_SetPermutationGLSL(mode, permutation);
2978 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2979 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2980 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2981 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2982 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2983 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2984 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]);
2985 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));
2986 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2987 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2989 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2990 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2991 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2992 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2993 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2994 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2999 #define SKINFRAME_HASH 1024
3003 int loadsequence; // incremented each level change
3004 memexpandablearray_t array;
3005 skinframe_t *hash[SKINFRAME_HASH];
3008 r_skinframe_t r_skinframe;
3010 void R_SkinFrame_PrepareForPurge(void)
3012 r_skinframe.loadsequence++;
3013 // wrap it without hitting zero
3014 if (r_skinframe.loadsequence >= 200)
3015 r_skinframe.loadsequence = 1;
3018 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3022 // mark the skinframe as used for the purging code
3023 skinframe->loadsequence = r_skinframe.loadsequence;
3026 void R_SkinFrame_Purge(void)
3030 for (i = 0;i < SKINFRAME_HASH;i++)
3032 for (s = r_skinframe.hash[i];s;s = s->next)
3034 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3036 if (s->merged == s->base)
3038 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3039 R_PurgeTexture(s->stain );s->stain = NULL;
3040 R_PurgeTexture(s->merged);s->merged = NULL;
3041 R_PurgeTexture(s->base );s->base = NULL;
3042 R_PurgeTexture(s->pants );s->pants = NULL;
3043 R_PurgeTexture(s->shirt );s->shirt = NULL;
3044 R_PurgeTexture(s->nmap );s->nmap = NULL;
3045 R_PurgeTexture(s->gloss );s->gloss = NULL;
3046 R_PurgeTexture(s->glow );s->glow = NULL;
3047 R_PurgeTexture(s->fog );s->fog = NULL;
3048 R_PurgeTexture(s->reflect);s->reflect = NULL;
3049 s->loadsequence = 0;
3055 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3057 char basename[MAX_QPATH];
3059 Image_StripImageExtension(name, basename, sizeof(basename));
3061 if( last == NULL ) {
3063 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3064 item = r_skinframe.hash[hashindex];
3069 // linearly search through the hash bucket
3070 for( ; item ; item = item->next ) {
3071 if( !strcmp( item->basename, basename ) ) {
3078 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3082 char basename[MAX_QPATH];
3084 Image_StripImageExtension(name, basename, sizeof(basename));
3086 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3087 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3088 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3092 rtexture_t *dyntexture;
3093 // check whether its a dynamic texture
3094 dyntexture = CL_GetDynTexture( basename );
3095 if (!add && !dyntexture)
3097 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3098 memset(item, 0, sizeof(*item));
3099 strlcpy(item->basename, basename, sizeof(item->basename));
3100 item->base = dyntexture; // either NULL or dyntexture handle
3101 item->textureflags = textureflags;
3102 item->comparewidth = comparewidth;
3103 item->compareheight = compareheight;
3104 item->comparecrc = comparecrc;
3105 item->next = r_skinframe.hash[hashindex];
3106 r_skinframe.hash[hashindex] = item;
3108 else if( item->base == NULL )
3110 rtexture_t *dyntexture;
3111 // check whether its a dynamic texture
3112 // 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]
3113 dyntexture = CL_GetDynTexture( basename );
3114 item->base = dyntexture; // either NULL or dyntexture handle
3117 R_SkinFrame_MarkUsed(item);
3121 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3123 unsigned long long avgcolor[5], wsum; \
3131 for(pix = 0; pix < cnt; ++pix) \
3134 for(comp = 0; comp < 3; ++comp) \
3136 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3139 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3141 for(comp = 0; comp < 3; ++comp) \
3142 avgcolor[comp] += getpixel * w; \
3145 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3146 avgcolor[4] += getpixel; \
3148 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3150 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3151 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3152 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3153 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3156 extern cvar_t gl_picmip;
3157 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3160 unsigned char *pixels;
3161 unsigned char *bumppixels;
3162 unsigned char *basepixels = NULL;
3163 int basepixels_width = 0;
3164 int basepixels_height = 0;
3165 skinframe_t *skinframe;
3166 rtexture_t *ddsbase = NULL;
3167 qboolean ddshasalpha = false;
3168 float ddsavgcolor[4];
3169 char basename[MAX_QPATH];
3170 int miplevel = R_PicmipForFlags(textureflags);
3171 int savemiplevel = miplevel;
3174 if (cls.state == ca_dedicated)
3177 // return an existing skinframe if already loaded
3178 // if loading of the first image fails, don't make a new skinframe as it
3179 // would cause all future lookups of this to be missing
3180 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3181 if (skinframe && skinframe->base)
3184 Image_StripImageExtension(name, basename, sizeof(basename));
3186 // check for DDS texture file first
3187 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3189 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3190 if (basepixels == NULL)
3194 // FIXME handle miplevel
3196 if (developer_loading.integer)
3197 Con_Printf("loading skin \"%s\"\n", name);
3199 // we've got some pixels to store, so really allocate this new texture now
3201 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3202 skinframe->stain = NULL;
3203 skinframe->merged = NULL;
3204 skinframe->base = NULL;
3205 skinframe->pants = NULL;
3206 skinframe->shirt = NULL;
3207 skinframe->nmap = NULL;
3208 skinframe->gloss = NULL;
3209 skinframe->glow = NULL;
3210 skinframe->fog = NULL;
3211 skinframe->reflect = NULL;
3212 skinframe->hasalpha = false;
3216 skinframe->base = ddsbase;
3217 skinframe->hasalpha = ddshasalpha;
3218 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3219 if (r_loadfog && skinframe->hasalpha)
3220 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3221 //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]);
3225 basepixels_width = image_width;
3226 basepixels_height = image_height;
3227 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3228 if (textureflags & TEXF_ALPHA)
3230 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3232 if (basepixels[j] < 255)
3234 skinframe->hasalpha = true;
3238 if (r_loadfog && skinframe->hasalpha)
3240 // has transparent pixels
3241 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3242 for (j = 0;j < image_width * image_height * 4;j += 4)
3247 pixels[j+3] = basepixels[j+3];
3249 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);
3253 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3254 //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]);
3255 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3256 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3257 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3258 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3263 mymiplevel = savemiplevel;
3264 if (r_loadnormalmap)
3265 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);
3266 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3270 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274 // _norm is the name used by tenebrae and has been adopted as standard
3275 if (r_loadnormalmap && skinframe->nmap == NULL)
3277 mymiplevel = savemiplevel;
3278 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3280 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);
3284 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3286 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3287 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3288 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);
3290 Mem_Free(bumppixels);
3292 else if (r_shadow_bumpscale_basetexture.value > 0)
3294 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3295 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3296 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);
3299 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3300 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3303 // _luma is supported only for tenebrae compatibility
3304 // _glow is the preferred name
3305 mymiplevel = savemiplevel;
3306 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3308 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3309 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3310 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3311 Mem_Free(pixels);pixels = NULL;
3314 mymiplevel = savemiplevel;
3315 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3317 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3318 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3319 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3324 mymiplevel = savemiplevel;
3325 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3327 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3328 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3329 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3334 mymiplevel = savemiplevel;
3335 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3337 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3338 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3339 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3344 mymiplevel = savemiplevel;
3345 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3347 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3348 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3349 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3355 Mem_Free(basepixels);
3360 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3361 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3364 unsigned char *temp1, *temp2;
3365 skinframe_t *skinframe;
3367 if (cls.state == ca_dedicated)
3370 // if already loaded just return it, otherwise make a new skinframe
3371 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3372 if (skinframe && skinframe->base)
3375 skinframe->stain = NULL;
3376 skinframe->merged = NULL;
3377 skinframe->base = NULL;
3378 skinframe->pants = NULL;
3379 skinframe->shirt = NULL;
3380 skinframe->nmap = NULL;
3381 skinframe->gloss = NULL;
3382 skinframe->glow = NULL;
3383 skinframe->fog = NULL;
3384 skinframe->reflect = NULL;
3385 skinframe->hasalpha = false;
3387 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3391 if (developer_loading.integer)
3392 Con_Printf("loading 32bit skin \"%s\"\n", name);
3394 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3396 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3397 temp2 = temp1 + width * height * 4;
3398 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3399 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);
3402 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3403 if (textureflags & TEXF_ALPHA)
3405 for (i = 3;i < width * height * 4;i += 4)
3407 if (skindata[i] < 255)
3409 skinframe->hasalpha = true;
3413 if (r_loadfog && skinframe->hasalpha)
3415 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3416 memcpy(fogpixels, skindata, width * height * 4);
3417 for (i = 0;i < width * height * 4;i += 4)
3418 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3419 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3420 Mem_Free(fogpixels);
3424 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3425 //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]);
3430 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3434 skinframe_t *skinframe;
3436 if (cls.state == ca_dedicated)
3439 // if already loaded just return it, otherwise make a new skinframe
3440 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3441 if (skinframe && skinframe->base)
3444 skinframe->stain = NULL;
3445 skinframe->merged = NULL;
3446 skinframe->base = NULL;
3447 skinframe->pants = NULL;
3448 skinframe->shirt = NULL;
3449 skinframe->nmap = NULL;
3450 skinframe->gloss = NULL;
3451 skinframe->glow = NULL;
3452 skinframe->fog = NULL;
3453 skinframe->reflect = NULL;
3454 skinframe->hasalpha = false;
3456 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3460 if (developer_loading.integer)
3461 Con_Printf("loading quake skin \"%s\"\n", name);
3463 // 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)
3464 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3465 memcpy(skinframe->qpixels, skindata, width*height);
3466 skinframe->qwidth = width;
3467 skinframe->qheight = height;
3470 for (i = 0;i < width * height;i++)
3471 featuresmask |= palette_featureflags[skindata[i]];
3473 skinframe->hasalpha = false;
3474 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3475 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3476 skinframe->qgeneratemerged = true;
3477 skinframe->qgeneratebase = skinframe->qhascolormapping;
3478 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3480 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3481 //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]);
3486 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3490 unsigned char *skindata;
3492 if (!skinframe->qpixels)
3495 if (!skinframe->qhascolormapping)
3496 colormapped = false;
3500 if (!skinframe->qgeneratebase)
3505 if (!skinframe->qgeneratemerged)
3509 width = skinframe->qwidth;
3510 height = skinframe->qheight;
3511 skindata = skinframe->qpixels;
3513 if (skinframe->qgeneratenmap)
3515 unsigned char *temp1, *temp2;
3516 skinframe->qgeneratenmap = false;
3517 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3518 temp2 = temp1 + width * height * 4;
3519 // use either a custom palette or the quake palette
3520 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3521 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3522 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);
3526 if (skinframe->qgenerateglow)
3528 skinframe->qgenerateglow = false;
3529 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3534 skinframe->qgeneratebase = false;
3535 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);
3536 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3537 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3541 skinframe->qgeneratemerged = false;
3542 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);
3545 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3547 Mem_Free(skinframe->qpixels);
3548 skinframe->qpixels = NULL;
3552 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)
3555 skinframe_t *skinframe;
3557 if (cls.state == ca_dedicated)
3560 // if already loaded just return it, otherwise make a new skinframe
3561 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3562 if (skinframe && skinframe->base)
3565 skinframe->stain = NULL;
3566 skinframe->merged = NULL;
3567 skinframe->base = NULL;
3568 skinframe->pants = NULL;
3569 skinframe->shirt = NULL;
3570 skinframe->nmap = NULL;
3571 skinframe->gloss = NULL;
3572 skinframe->glow = NULL;
3573 skinframe->fog = NULL;
3574 skinframe->reflect = NULL;
3575 skinframe->hasalpha = false;
3577 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3581 if (developer_loading.integer)
3582 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3584 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3585 if (textureflags & TEXF_ALPHA)
3587 for (i = 0;i < width * height;i++)
3589 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3591 skinframe->hasalpha = true;
3595 if (r_loadfog && skinframe->hasalpha)
3596 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3599 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3600 //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]);
3605 skinframe_t *R_SkinFrame_LoadMissing(void)
3607 skinframe_t *skinframe;
3609 if (cls.state == ca_dedicated)
3612 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3613 skinframe->stain = NULL;
3614 skinframe->merged = NULL;
3615 skinframe->base = NULL;
3616 skinframe->pants = NULL;
3617 skinframe->shirt = NULL;
3618 skinframe->nmap = NULL;
3619 skinframe->gloss = NULL;
3620 skinframe->glow = NULL;
3621 skinframe->fog = NULL;
3622 skinframe->reflect = NULL;
3623 skinframe->hasalpha = false;
3625 skinframe->avgcolor[0] = rand() / RAND_MAX;
3626 skinframe->avgcolor[1] = rand() / RAND_MAX;
3627 skinframe->avgcolor[2] = rand() / RAND_MAX;
3628 skinframe->avgcolor[3] = 1;
3633 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3634 typedef struct suffixinfo_s
3637 qboolean flipx, flipy, flipdiagonal;
3640 static suffixinfo_t suffix[3][6] =
3643 {"px", false, false, false},
3644 {"nx", false, false, false},
3645 {"py", false, false, false},
3646 {"ny", false, false, false},
3647 {"pz", false, false, false},
3648 {"nz", false, false, false}
3651 {"posx", false, false, false},
3652 {"negx", false, false, false},
3653 {"posy", false, false, false},
3654 {"negy", false, false, false},
3655 {"posz", false, false, false},
3656 {"negz", false, false, false}
3659 {"rt", true, false, true},
3660 {"lf", false, true, true},
3661 {"ft", true, true, false},
3662 {"bk", false, false, false},
3663 {"up", true, false, true},
3664 {"dn", true, false, true}
3668 static int componentorder[4] = {0, 1, 2, 3};
3670 rtexture_t *R_LoadCubemap(const char *basename)
3672 int i, j, cubemapsize;
3673 unsigned char *cubemappixels, *image_buffer;
3674 rtexture_t *cubemaptexture;
3676 // must start 0 so the first loadimagepixels has no requested width/height
3678 cubemappixels = NULL;
3679 cubemaptexture = NULL;
3680 // keep trying different suffix groups (posx, px, rt) until one loads
3681 for (j = 0;j < 3 && !cubemappixels;j++)
3683 // load the 6 images in the suffix group
3684 for (i = 0;i < 6;i++)
3686 // generate an image name based on the base and and suffix
3687 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3689 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3691 // an image loaded, make sure width and height are equal
3692 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3694 // if this is the first image to load successfully, allocate the cubemap memory
3695 if (!cubemappixels && image_width >= 1)
3697 cubemapsize = image_width;
3698 // note this clears to black, so unavailable sides are black
3699 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3701 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3703 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);
3706 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3708 Mem_Free(image_buffer);
3712 // if a cubemap loaded, upload it
3715 if (developer_loading.integer)
3716 Con_Printf("loading cubemap \"%s\"\n", basename);
3718 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3719 Mem_Free(cubemappixels);
3723 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3724 if (developer_loading.integer)
3726 Con_Printf("(tried tried images ");
3727 for (j = 0;j < 3;j++)
3728 for (i = 0;i < 6;i++)
3729 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3730 Con_Print(" and was unable to find any of them).\n");
3733 return cubemaptexture;
3736 rtexture_t *R_GetCubemap(const char *basename)
3739 for (i = 0;i < r_texture_numcubemaps;i++)
3740 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3741 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3742 if (i >= MAX_CUBEMAPS)
3743 return r_texture_whitecube;
3744 r_texture_numcubemaps++;
3745 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3746 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3747 return r_texture_cubemaps[i].texture;
3750 void R_FreeCubemaps(void)
3753 for (i = 0;i < r_texture_numcubemaps;i++)
3755 if (developer_loading.integer)
3756 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3757 if (r_texture_cubemaps[i].texture)
3758 R_FreeTexture(r_texture_cubemaps[i].texture);
3760 r_texture_numcubemaps = 0;
3763 void R_Main_FreeViewCache(void)
3765 if (r_refdef.viewcache.entityvisible)
3766 Mem_Free(r_refdef.viewcache.entityvisible);
3767 if (r_refdef.viewcache.world_pvsbits)
3768 Mem_Free(r_refdef.viewcache.world_pvsbits);
3769 if (r_refdef.viewcache.world_leafvisible)
3770 Mem_Free(r_refdef.viewcache.world_leafvisible);
3771 if (r_refdef.viewcache.world_surfacevisible)
3772 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3773 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3776 void R_Main_ResizeViewCache(void)
3778 int numentities = r_refdef.scene.numentities;
3779 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3780 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3781 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3782 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3783 if (r_refdef.viewcache.maxentities < numentities)
3785 r_refdef.viewcache.maxentities = numentities;
3786 if (r_refdef.viewcache.entityvisible)
3787 Mem_Free(r_refdef.viewcache.entityvisible);
3788 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3790 if (r_refdef.viewcache.world_numclusters != numclusters)
3792 r_refdef.viewcache.world_numclusters = numclusters;
3793 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3794 if (r_refdef.viewcache.world_pvsbits)
3795 Mem_Free(r_refdef.viewcache.world_pvsbits);
3796 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3798 if (r_refdef.viewcache.world_numleafs != numleafs)
3800 r_refdef.viewcache.world_numleafs = numleafs;
3801 if (r_refdef.viewcache.world_leafvisible)
3802 Mem_Free(r_refdef.viewcache.world_leafvisible);
3803 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3805 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3807 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3808 if (r_refdef.viewcache.world_surfacevisible)
3809 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3810 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3814 extern rtexture_t *loadingscreentexture;
3815 void gl_main_start(void)
3817 loadingscreentexture = NULL;
3818 r_texture_blanknormalmap = NULL;
3819 r_texture_white = NULL;
3820 r_texture_grey128 = NULL;
3821 r_texture_black = NULL;
3822 r_texture_whitecube = NULL;
3823 r_texture_normalizationcube = NULL;
3824 r_texture_fogattenuation = NULL;
3825 r_texture_fogheighttexture = NULL;
3826 r_texture_gammaramps = NULL;
3827 r_texture_numcubemaps = 0;
3829 r_loaddds = r_texture_dds_load.integer != 0;
3830 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3832 switch(vid.renderpath)
3834 case RENDERPATH_GL20:
3835 case RENDERPATH_D3D9:
3836 case RENDERPATH_D3D10:
3837 case RENDERPATH_D3D11:
3838 case RENDERPATH_SOFT:
3839 case RENDERPATH_GLES2:
3840 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3841 Cvar_SetValueQuick(&gl_combine, 1);
3842 Cvar_SetValueQuick(&r_glsl, 1);
3843 r_loadnormalmap = true;
3847 case RENDERPATH_GL13:
3848 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3849 Cvar_SetValueQuick(&gl_combine, 1);
3850 Cvar_SetValueQuick(&r_glsl, 0);
3851 r_loadnormalmap = false;
3852 r_loadgloss = false;
3855 case RENDERPATH_GL11:
3856 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3857 Cvar_SetValueQuick(&gl_combine, 0);
3858 Cvar_SetValueQuick(&r_glsl, 0);
3859 r_loadnormalmap = false;
3860 r_loadgloss = false;
3866 R_FrameData_Reset();
3870 memset(r_queries, 0, sizeof(r_queries));
3872 r_qwskincache = NULL;
3873 r_qwskincache_size = 0;
3875 // due to caching of texture_t references, the collision cache must be reset
3876 Collision_Cache_Reset(true);
3878 // set up r_skinframe loading system for textures
3879 memset(&r_skinframe, 0, sizeof(r_skinframe));
3880 r_skinframe.loadsequence = 1;
3881 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3883 r_main_texturepool = R_AllocTexturePool();
3884 R_BuildBlankTextures();
3886 if (vid.support.arb_texture_cube_map)
3889 R_BuildNormalizationCube();
3891 r_texture_fogattenuation = NULL;
3892 r_texture_fogheighttexture = NULL;
3893 r_texture_gammaramps = NULL;
3894 //r_texture_fogintensity = NULL;
3895 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3896 memset(&r_waterstate, 0, sizeof(r_waterstate));
3897 r_glsl_permutation = NULL;
3898 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3899 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3900 glslshaderstring = NULL;
3902 r_hlsl_permutation = NULL;
3903 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3904 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3906 hlslshaderstring = NULL;
3907 memset(&r_svbsp, 0, sizeof (r_svbsp));
3909 r_refdef.fogmasktable_density = 0;
3912 void gl_main_shutdown(void)
3915 R_FrameData_Reset();
3917 R_Main_FreeViewCache();
3919 switch(vid.renderpath)
3921 case RENDERPATH_GL11:
3922 case RENDERPATH_GL13:
3923 case RENDERPATH_GL20:
3924 case RENDERPATH_GLES2:
3926 qglDeleteQueriesARB(r_maxqueries, r_queries);
3928 case RENDERPATH_D3D9:
3929 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3931 case RENDERPATH_D3D10:
3932 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3934 case RENDERPATH_D3D11:
3935 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3937 case RENDERPATH_SOFT:
3943 memset(r_queries, 0, sizeof(r_queries));
3945 r_qwskincache = NULL;
3946 r_qwskincache_size = 0;
3948 // clear out the r_skinframe state
3949 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3950 memset(&r_skinframe, 0, sizeof(r_skinframe));
3953 Mem_Free(r_svbsp.nodes);
3954 memset(&r_svbsp, 0, sizeof (r_svbsp));
3955 R_FreeTexturePool(&r_main_texturepool);
3956 loadingscreentexture = NULL;
3957 r_texture_blanknormalmap = NULL;
3958 r_texture_white = NULL;
3959 r_texture_grey128 = NULL;
3960 r_texture_black = NULL;
3961 r_texture_whitecube = NULL;
3962 r_texture_normalizationcube = NULL;
3963 r_texture_fogattenuation = NULL;
3964 r_texture_fogheighttexture = NULL;
3965 r_texture_gammaramps = NULL;
3966 r_texture_numcubemaps = 0;
3967 //r_texture_fogintensity = NULL;
3968 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3969 memset(&r_waterstate, 0, sizeof(r_waterstate));
3972 r_glsl_permutation = NULL;
3973 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3974 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3975 glslshaderstring = NULL;
3977 r_hlsl_permutation = NULL;
3978 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3979 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3981 hlslshaderstring = NULL;
3984 extern void CL_ParseEntityLump(char *entitystring);
3985 void gl_main_newmap(void)
3987 // FIXME: move this code to client
3988 char *entities, entname[MAX_QPATH];
3990 Mem_Free(r_qwskincache);
3991 r_qwskincache = NULL;
3992 r_qwskincache_size = 0;
3995 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3996 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3998 CL_ParseEntityLump(entities);
4002 if (cl.worldmodel->brush.entities)
4003 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4005 R_Main_FreeViewCache();
4007 R_FrameData_Reset();
4010 void GL_Main_Init(void)
4012 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4014 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4015 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4016 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4017 if (gamemode == GAME_NEHAHRA)
4019 Cvar_RegisterVariable (&gl_fogenable);
4020 Cvar_RegisterVariable (&gl_fogdensity);
4021 Cvar_RegisterVariable (&gl_fogred);
4022 Cvar_RegisterVariable (&gl_foggreen);
4023 Cvar_RegisterVariable (&gl_fogblue);
4024 Cvar_RegisterVariable (&gl_fogstart);
4025 Cvar_RegisterVariable (&gl_fogend);
4026 Cvar_RegisterVariable (&gl_skyclip);
4028 Cvar_RegisterVariable(&r_motionblur);
4029 Cvar_RegisterVariable(&r_motionblur_maxblur);
4030 Cvar_RegisterVariable(&r_motionblur_bmin);
4031 Cvar_RegisterVariable(&r_motionblur_vmin);
4032 Cvar_RegisterVariable(&r_motionblur_vmax);
4033 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4034 Cvar_RegisterVariable(&r_motionblur_randomize);
4035 Cvar_RegisterVariable(&r_damageblur);
4036 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4037 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4038 Cvar_RegisterVariable(&r_equalize_entities_by);
4039 Cvar_RegisterVariable(&r_equalize_entities_to);
4040 Cvar_RegisterVariable(&r_depthfirst);
4041 Cvar_RegisterVariable(&r_useinfinitefarclip);
4042 Cvar_RegisterVariable(&r_farclip_base);
4043 Cvar_RegisterVariable(&r_farclip_world);
4044 Cvar_RegisterVariable(&r_nearclip);
4045 Cvar_RegisterVariable(&r_showbboxes);
4046 Cvar_RegisterVariable(&r_showsurfaces);
4047 Cvar_RegisterVariable(&r_showtris);
4048 Cvar_RegisterVariable(&r_shownormals);
4049 Cvar_RegisterVariable(&r_showlighting);
4050 Cvar_RegisterVariable(&r_showshadowvolumes);
4051 Cvar_RegisterVariable(&r_showcollisionbrushes);
4052 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4053 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4054 Cvar_RegisterVariable(&r_showdisabledepthtest);
4055 Cvar_RegisterVariable(&r_drawportals);
4056 Cvar_RegisterVariable(&r_drawentities);
4057 Cvar_RegisterVariable(&r_draw2d);
4058 Cvar_RegisterVariable(&r_drawworld);
4059 Cvar_RegisterVariable(&r_cullentities_trace);
4060 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4061 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4062 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4063 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4064 Cvar_RegisterVariable(&r_drawviewmodel);
4065 Cvar_RegisterVariable(&r_drawexteriormodel);
4066 Cvar_RegisterVariable(&r_speeds);
4067 Cvar_RegisterVariable(&r_fullbrights);
4068 Cvar_RegisterVariable(&r_wateralpha);
4069 Cvar_RegisterVariable(&r_dynamic);
4070 Cvar_RegisterVariable(&r_fakelight);
4071 Cvar_RegisterVariable(&r_fakelight_intensity);
4072 Cvar_RegisterVariable(&r_fullbright);
4073 Cvar_RegisterVariable(&r_shadows);
4074 Cvar_RegisterVariable(&r_shadows_darken);
4075 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4076 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4077 Cvar_RegisterVariable(&r_shadows_throwdistance);
4078 Cvar_RegisterVariable(&r_shadows_throwdirection);
4079 Cvar_RegisterVariable(&r_shadows_focus);
4080 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4081 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4082 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4083 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4084 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4085 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4086 Cvar_RegisterVariable(&r_fog_exp2);
4087 Cvar_RegisterVariable(&r_fog_clear);
4088 Cvar_RegisterVariable(&r_drawfog);
4089 Cvar_RegisterVariable(&r_transparentdepthmasking);
4090 Cvar_RegisterVariable(&r_texture_dds_load);
4091 Cvar_RegisterVariable(&r_texture_dds_save);
4092 Cvar_RegisterVariable(&r_texture_sRGB_2d);
4093 Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4094 Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4095 Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4096 Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4097 Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4098 Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4099 Cvar_RegisterVariable(&r_textureunits);
4100 Cvar_RegisterVariable(&gl_combine);
4101 Cvar_RegisterVariable(&r_viewfbo);
4102 Cvar_RegisterVariable(&r_viewscale);
4103 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4104 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4105 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4106 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4107 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4108 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4109 Cvar_RegisterVariable(&r_glsl);
4110 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4111 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4112 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4113 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4114 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4115 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4116 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4117 Cvar_RegisterVariable(&r_glsl_postprocess);
4118 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4119 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4120 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4121 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4122 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4123 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4124 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4125 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4127 Cvar_RegisterVariable(&r_water);
4128 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4129 Cvar_RegisterVariable(&r_water_clippingplanebias);
4130 Cvar_RegisterVariable(&r_water_refractdistort);
4131 Cvar_RegisterVariable(&r_water_reflectdistort);
4132 Cvar_RegisterVariable(&r_water_scissormode);
4133 Cvar_RegisterVariable(&r_lerpsprites);
4134 Cvar_RegisterVariable(&r_lerpmodels);
4135 Cvar_RegisterVariable(&r_lerplightstyles);
4136 Cvar_RegisterVariable(&r_waterscroll);
4137 Cvar_RegisterVariable(&r_bloom);
4138 Cvar_RegisterVariable(&r_bloom_colorscale);
4139 Cvar_RegisterVariable(&r_bloom_brighten);
4140 Cvar_RegisterVariable(&r_bloom_blur);
4141 Cvar_RegisterVariable(&r_bloom_resolution);
4142 Cvar_RegisterVariable(&r_bloom_colorexponent);
4143 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4144 Cvar_RegisterVariable(&r_hdr);
4145 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4146 Cvar_RegisterVariable(&r_hdr_glowintensity);
4147 Cvar_RegisterVariable(&r_hdr_range);
4148 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4149 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4150 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4151 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4152 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4153 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4154 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4155 Cvar_RegisterVariable(&developer_texturelogging);
4156 Cvar_RegisterVariable(&gl_lightmaps);
4157 Cvar_RegisterVariable(&r_test);
4158 Cvar_RegisterVariable(&r_glsl_saturation);
4159 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4160 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4161 Cvar_RegisterVariable(&r_framedatasize);
4162 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4163 Cvar_SetValue("r_fullbrights", 0);
4164 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4166 Cvar_RegisterVariable(&r_track_sprites);
4167 Cvar_RegisterVariable(&r_track_sprites_flags);
4168 Cvar_RegisterVariable(&r_track_sprites_scalew);
4169 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4170 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4171 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4172 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4173 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4176 extern void R_Textures_Init(void);
4177 extern void GL_Draw_Init(void);
4178 extern void GL_Main_Init(void);
4179 extern void R_Shadow_Init(void);
4180 extern void R_Sky_Init(void);
4181 extern void GL_Surf_Init(void);
4182 extern void R_Particles_Init(void);
4183 extern void R_Explosion_Init(void);
4184 extern void gl_backend_init(void);
4185 extern void Sbar_Init(void);
4186 extern void R_LightningBeams_Init(void);
4187 extern void Mod_RenderInit(void);
4188 extern void Font_Init(void);
4190 void Render_Init(void)
4203 R_LightningBeams_Init();
4212 extern char *ENGINE_EXTENSIONS;
4215 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4216 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4217 gl_version = (const char *)qglGetString(GL_VERSION);
4218 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4222 if (!gl_platformextensions)
4223 gl_platformextensions = "";
4225 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4226 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4227 Con_Printf("GL_VERSION: %s\n", gl_version);
4228 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4229 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4231 VID_CheckExtensions();
4233 // LordHavoc: report supported extensions
4234 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4236 // clear to black (loading plaque will be seen over this)
4237 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4240 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4244 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4246 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4249 p = r_refdef.view.frustum + i;
4254 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4258 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4262 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4266 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4270 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4274 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4278 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4282 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4290 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4294 for (i = 0;i < numplanes;i++)
4301 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4305 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4309 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4313 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4317 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4321 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4325 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4329 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4337 //==================================================================================
4339 // LordHavoc: this stores temporary data used within the same frame
4341 typedef struct r_framedata_mem_s
4343 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4344 size_t size; // how much usable space
4345 size_t current; // how much space in use
4346 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4347 size_t wantedsize; // how much space was allocated
4348 unsigned char *data; // start of real data (16byte aligned)
4352 static r_framedata_mem_t *r_framedata_mem;
4354 void R_FrameData_Reset(void)
4356 while (r_framedata_mem)
4358 r_framedata_mem_t *next = r_framedata_mem->purge;
4359 Mem_Free(r_framedata_mem);
4360 r_framedata_mem = next;
4364 void R_FrameData_Resize(void)
4367 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4368 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4369 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4371 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4372 newmem->wantedsize = wantedsize;
4373 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4374 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4375 newmem->current = 0;
4377 newmem->purge = r_framedata_mem;
4378 r_framedata_mem = newmem;
4382 void R_FrameData_NewFrame(void)
4384 R_FrameData_Resize();
4385 if (!r_framedata_mem)
4387 // if we ran out of space on the last frame, free the old memory now
4388 while (r_framedata_mem->purge)
4390 // repeatedly remove the second item in the list, leaving only head
4391 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4392 Mem_Free(r_framedata_mem->purge);
4393 r_framedata_mem->purge = next;
4395 // reset the current mem pointer
4396 r_framedata_mem->current = 0;
4397 r_framedata_mem->mark = 0;
4400 void *R_FrameData_Alloc(size_t size)
4404 // align to 16 byte boundary - the data pointer is already aligned, so we
4405 // only need to ensure the size of every allocation is also aligned
4406 size = (size + 15) & ~15;
4408 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4410 // emergency - we ran out of space, allocate more memory
4411 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4412 R_FrameData_Resize();
4415 data = r_framedata_mem->data + r_framedata_mem->current;
4416 r_framedata_mem->current += size;
4418 // count the usage for stats
4419 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4420 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4422 return (void *)data;
4425 void *R_FrameData_Store(size_t size, void *data)
4427 void *d = R_FrameData_Alloc(size);
4429 memcpy(d, data, size);
4433 void R_FrameData_SetMark(void)
4435 if (!r_framedata_mem)
4437 r_framedata_mem->mark = r_framedata_mem->current;
4440 void R_FrameData_ReturnToMark(void)
4442 if (!r_framedata_mem)
4444 r_framedata_mem->current = r_framedata_mem->mark;
4447 //==================================================================================
4449 // LordHavoc: animcache originally written by Echon, rewritten since then
4452 * Animation cache prevents re-generating mesh data for an animated model
4453 * multiple times in one frame for lighting, shadowing, reflections, etc.
4456 void R_AnimCache_Free(void)
4460 void R_AnimCache_ClearCache(void)
4463 entity_render_t *ent;
4465 for (i = 0;i < r_refdef.scene.numentities;i++)
4467 ent = r_refdef.scene.entities[i];
4468 ent->animcache_vertex3f = NULL;
4469 ent->animcache_normal3f = NULL;
4470 ent->animcache_svector3f = NULL;
4471 ent->animcache_tvector3f = NULL;
4472 ent->animcache_vertexmesh = NULL;
4473 ent->animcache_vertex3fbuffer = NULL;
4474 ent->animcache_vertexmeshbuffer = NULL;
4478 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4482 // check if we need the meshbuffers
4483 if (!vid.useinterleavedarrays)
4486 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4487 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4488 // TODO: upload vertex3f buffer?
4489 if (ent->animcache_vertexmesh)
4491 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4492 for (i = 0;i < numvertices;i++)
4493 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4494 if (ent->animcache_svector3f)
4495 for (i = 0;i < numvertices;i++)
4496 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4497 if (ent->animcache_tvector3f)
4498 for (i = 0;i < numvertices;i++)
4499 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4500 if (ent->animcache_normal3f)
4501 for (i = 0;i < numvertices;i++)
4502 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4503 // TODO: upload vertexmeshbuffer?
4507 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4509 dp_model_t *model = ent->model;
4511 // see if it's already cached this frame
4512 if (ent->animcache_vertex3f)
4514 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4515 if (wantnormals || wanttangents)
4517 if (ent->animcache_normal3f)
4518 wantnormals = false;
4519 if (ent->animcache_svector3f)
4520 wanttangents = false;
4521 if (wantnormals || wanttangents)
4523 numvertices = model->surfmesh.num_vertices;
4525 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4528 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4529 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4532 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4538 // see if this ent is worth caching
4539 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4541 // get some memory for this entity and generate mesh data
4542 numvertices = model->surfmesh.num_vertices;
4543 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4545 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4548 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4551 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4552 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4557 void R_AnimCache_CacheVisibleEntities(void)
4560 qboolean wantnormals = true;
4561 qboolean wanttangents = !r_showsurfaces.integer;
4563 switch(vid.renderpath)
4565 case RENDERPATH_GL20:
4566 case RENDERPATH_D3D9:
4567 case RENDERPATH_D3D10:
4568 case RENDERPATH_D3D11:
4569 case RENDERPATH_GLES2:
4571 case RENDERPATH_GL13:
4572 case RENDERPATH_GL11:
4573 wanttangents = false;
4575 case RENDERPATH_SOFT:
4579 if (r_shownormals.integer)
4580 wanttangents = wantnormals = true;
4582 // TODO: thread this
4583 // NOTE: R_PrepareRTLights() also caches entities
4585 for (i = 0;i < r_refdef.scene.numentities;i++)
4586 if (r_refdef.viewcache.entityvisible[i])
4587 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4590 //==================================================================================
4592 static void R_View_UpdateEntityLighting (void)
4595 entity_render_t *ent;
4596 vec3_t tempdiffusenormal, avg;
4597 vec_t f, fa, fd, fdd;
4598 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4600 for (i = 0;i < r_refdef.scene.numentities;i++)
4602 ent = r_refdef.scene.entities[i];
4604 // skip unseen models
4605 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4609 if (ent->model && ent->model->brush.num_leafs)
4611 // TODO: use modellight for r_ambient settings on world?
4612 VectorSet(ent->modellight_ambient, 0, 0, 0);
4613 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4614 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4618 // fetch the lighting from the worldmodel data
4619 VectorClear(ent->modellight_ambient);
4620 VectorClear(ent->modellight_diffuse);
4621 VectorClear(tempdiffusenormal);
4622 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4625 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4627 // complete lightning for lit sprites
4628 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4629 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4631 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4632 org[2] = org[2] + r_overheadsprites_pushback.value;
4633 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4636 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4638 if(ent->flags & RENDER_EQUALIZE)
4640 // first fix up ambient lighting...
4641 if(r_equalize_entities_minambient.value > 0)
4643 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4646 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4647 if(fa < r_equalize_entities_minambient.value * fd)
4650 // fa'/fd' = minambient
4651 // fa'+0.25*fd' = fa+0.25*fd
4653 // fa' = fd' * minambient
4654 // fd'*(0.25+minambient) = fa+0.25*fd
4656 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4657 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4659 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4660 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
4661 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4662 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4667 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4669 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4670 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4674 // adjust brightness and saturation to target
4675 avg[0] = avg[1] = avg[2] = fa / f;
4676 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4677 avg[0] = avg[1] = avg[2] = fd / f;
4678 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4684 VectorSet(ent->modellight_ambient, 1, 1, 1);
4686 // move the light direction into modelspace coordinates for lighting code
4687 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4688 if(VectorLength2(ent->modellight_lightdir) == 0)
4689 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4690 VectorNormalize(ent->modellight_lightdir);
4694 #define MAX_LINEOFSIGHTTRACES 64
4696 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4699 vec3_t boxmins, boxmaxs;
4702 dp_model_t *model = r_refdef.scene.worldmodel;
4704 if (!model || !model->brush.TraceLineOfSight)
4707 // expand the box a little
4708 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4709 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4710 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4711 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4712 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4713 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4715 // return true if eye is inside enlarged box
4716 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4720 VectorCopy(eye, start);
4721 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4722 if (model->brush.TraceLineOfSight(model, start, end))
4725 // try various random positions
4726 for (i = 0;i < numsamples;i++)
4728 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4729 if (model->brush.TraceLineOfSight(model, start, end))
4737 static void R_View_UpdateEntityVisible (void)
4742 entity_render_t *ent;
4744 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4745 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4746 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4747 : RENDER_EXTERIORMODEL;
4748 if (!r_drawviewmodel.integer)
4749 renderimask |= RENDER_VIEWMODEL;
4750 if (!r_drawexteriormodel.integer)
4751 renderimask |= RENDER_EXTERIORMODEL;
4752 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4754 // worldmodel can check visibility
4755 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4756 for (i = 0;i < r_refdef.scene.numentities;i++)
4758 ent = r_refdef.scene.entities[i];
4759 if (!(ent->flags & renderimask))
4760 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)))
4761 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))
4762 r_refdef.viewcache.entityvisible[i] = true;
4764 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4765 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4767 for (i = 0;i < r_refdef.scene.numentities;i++)
4769 ent = r_refdef.scene.entities[i];
4770 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4772 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4774 continue; // temp entities do pvs only
4775 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4776 ent->last_trace_visibility = realtime;
4777 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4778 r_refdef.viewcache.entityvisible[i] = 0;
4785 // no worldmodel or it can't check visibility
4786 for (i = 0;i < r_refdef.scene.numentities;i++)
4788 ent = r_refdef.scene.entities[i];
4789 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));
4794 /// only used if skyrendermasked, and normally returns false
4795 int R_DrawBrushModelsSky (void)
4798 entity_render_t *ent;
4801 for (i = 0;i < r_refdef.scene.numentities;i++)
4803 if (!r_refdef.viewcache.entityvisible[i])
4805 ent = r_refdef.scene.entities[i];
4806 if (!ent->model || !ent->model->DrawSky)
4808 ent->model->DrawSky(ent);
4814 static void R_DrawNoModel(entity_render_t *ent);
4815 static void R_DrawModels(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 r_refdef.stats.entities++;
4826 if (ent->model && ent->model->Draw != NULL)
4827 ent->model->Draw(ent);
4833 static void R_DrawModelsDepth(void)
4836 entity_render_t *ent;
4838 for (i = 0;i < r_refdef.scene.numentities;i++)
4840 if (!r_refdef.viewcache.entityvisible[i])
4842 ent = r_refdef.scene.entities[i];
4843 if (ent->model && ent->model->DrawDepth != NULL)
4844 ent->model->DrawDepth(ent);
4848 static void R_DrawModelsDebug(void)
4851 entity_render_t *ent;
4853 for (i = 0;i < r_refdef.scene.numentities;i++)
4855 if (!r_refdef.viewcache.entityvisible[i])
4857 ent = r_refdef.scene.entities[i];
4858 if (ent->model && ent->model->DrawDebug != NULL)
4859 ent->model->DrawDebug(ent);
4863 static void R_DrawModelsAddWaterPlanes(void)
4866 entity_render_t *ent;
4868 for (i = 0;i < r_refdef.scene.numentities;i++)
4870 if (!r_refdef.viewcache.entityvisible[i])
4872 ent = r_refdef.scene.entities[i];
4873 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4874 ent->model->DrawAddWaterPlanes(ent);
4878 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4880 if (r_hdr_irisadaptation.integer)
4884 vec3_t diffusenormal;
4889 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4890 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4891 brightness = max(0.0000001f, brightness);
4892 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4893 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4894 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4895 current = r_hdr_irisadaptation_value.value;
4897 current = min(current + adjust, goal);
4898 else if (current > goal)
4899 current = max(current - adjust, goal);
4900 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4901 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4903 else if (r_hdr_irisadaptation_value.value != 1.0f)
4904 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4907 static void R_View_SetFrustum(const int *scissor)
4910 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4911 vec3_t forward, left, up, origin, v;
4915 // flipped x coordinates (because x points left here)
4916 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4917 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4919 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4920 switch(vid.renderpath)
4922 case RENDERPATH_D3D9:
4923 case RENDERPATH_D3D10:
4924 case RENDERPATH_D3D11:
4925 // non-flipped y coordinates
4926 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4927 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4929 case RENDERPATH_SOFT:
4930 case RENDERPATH_GL11:
4931 case RENDERPATH_GL13:
4932 case RENDERPATH_GL20:
4933 case RENDERPATH_GLES2:
4934 // non-flipped y coordinates
4935 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4936 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4941 // we can't trust r_refdef.view.forward and friends in reflected scenes
4942 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4945 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4946 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4947 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4948 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4949 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4950 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4951 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4952 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4953 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4954 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4955 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4956 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4960 zNear = r_refdef.nearclip;
4961 nudge = 1.0 - 1.0 / (1<<23);
4962 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4963 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4964 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4965 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4966 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4967 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4968 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4969 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4975 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4976 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4977 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4978 r_refdef.view.frustum[0].dist = m[15] - m[12];
4980 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4981 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4982 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4983 r_refdef.view.frustum[1].dist = m[15] + m[12];
4985 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4986 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4987 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4988 r_refdef.view.frustum[2].dist = m[15] - m[13];
4990 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4991 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4992 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4993 r_refdef.view.frustum[3].dist = m[15] + m[13];
4995 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4996 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4997 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4998 r_refdef.view.frustum[4].dist = m[15] - m[14];
5000 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5001 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5002 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5003 r_refdef.view.frustum[5].dist = m[15] + m[14];
5006 if (r_refdef.view.useperspective)
5008 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5009 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]);
5010 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]);
5011 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]);
5012 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]);
5014 // then the normals from the corners relative to origin
5015 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5016 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5017 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5018 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5020 // in a NORMAL view, forward cross left == up
5021 // in a REFLECTED view, forward cross left == down
5022 // so our cross products above need to be adjusted for a left handed coordinate system
5023 CrossProduct(forward, left, v);
5024 if(DotProduct(v, up) < 0)
5026 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5027 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5028 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5029 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5032 // Leaving those out was a mistake, those were in the old code, and they
5033 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5034 // I couldn't reproduce it after adding those normalizations. --blub
5035 VectorNormalize(r_refdef.view.frustum[0].normal);
5036 VectorNormalize(r_refdef.view.frustum[1].normal);
5037 VectorNormalize(r_refdef.view.frustum[2].normal);
5038 VectorNormalize(r_refdef.view.frustum[3].normal);
5040 // make the corners absolute
5041 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5042 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5043 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5044 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5047 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5049 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5050 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5051 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5052 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5053 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5057 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5058 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5059 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5060 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5061 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5062 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5063 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5064 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5065 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5066 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5068 r_refdef.view.numfrustumplanes = 5;
5070 if (r_refdef.view.useclipplane)
5072 r_refdef.view.numfrustumplanes = 6;
5073 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5076 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5077 PlaneClassify(r_refdef.view.frustum + i);
5079 // LordHavoc: note to all quake engine coders, Quake had a special case
5080 // for 90 degrees which assumed a square view (wrong), so I removed it,
5081 // Quake2 has it disabled as well.
5083 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5084 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5085 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5086 //PlaneClassify(&frustum[0]);
5088 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5089 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5090 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5091 //PlaneClassify(&frustum[1]);
5093 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5094 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5095 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5096 //PlaneClassify(&frustum[2]);
5098 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5099 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5100 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5101 //PlaneClassify(&frustum[3]);
5104 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5105 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5106 //PlaneClassify(&frustum[4]);
5109 void R_View_UpdateWithScissor(const int *myscissor)
5111 R_Main_ResizeViewCache();
5112 R_View_SetFrustum(myscissor);
5113 R_View_WorldVisibility(r_refdef.view.useclipplane);
5114 R_View_UpdateEntityVisible();
5115 R_View_UpdateEntityLighting();
5118 void R_View_Update(void)
5120 R_Main_ResizeViewCache();
5121 R_View_SetFrustum(NULL);
5122 R_View_WorldVisibility(r_refdef.view.useclipplane);
5123 R_View_UpdateEntityVisible();
5124 R_View_UpdateEntityLighting();
5127 float viewscalefpsadjusted = 1.0f;
5129 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5131 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5132 scale = bound(0.03125f, scale, 1.0f);
5133 *outwidth = (int)ceil(width * scale);
5134 *outheight = (int)ceil(height * scale);
5137 void R_Mesh_SetMainRenderTargets(void)
5139 if (r_bloomstate.fbo_framebuffer)
5140 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5142 R_Mesh_ResetRenderTargets();
5145 void R_SetupView(qboolean allowwaterclippingplane)
5147 const float *customclipplane = NULL;
5149 int scaledwidth, scaledheight;
5150 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5152 // LordHavoc: couldn't figure out how to make this approach the
5153 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5154 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5155 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5156 dist = r_refdef.view.clipplane.dist;
5157 plane[0] = r_refdef.view.clipplane.normal[0];
5158 plane[1] = r_refdef.view.clipplane.normal[1];
5159 plane[2] = r_refdef.view.clipplane.normal[2];
5161 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5164 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5165 if (!r_refdef.view.useperspective)
5166 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -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);
5167 else if (vid.stencil && r_useinfinitefarclip.integer)
5168 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5170 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5171 R_Mesh_SetMainRenderTargets();
5172 R_SetViewport(&r_refdef.view.viewport);
5173 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5175 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5176 float screenplane[4];
5177 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5178 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5179 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5180 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5181 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5185 void R_EntityMatrix(const matrix4x4_t *matrix)
5187 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5189 gl_modelmatrixchanged = false;
5190 gl_modelmatrix = *matrix;
5191 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5192 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5193 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5194 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5196 switch(vid.renderpath)
5198 case RENDERPATH_D3D9:
5200 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5201 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5204 case RENDERPATH_D3D10:
5205 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5207 case RENDERPATH_D3D11:
5208 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5210 case RENDERPATH_GL13:
5211 case RENDERPATH_GL11:
5212 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5214 case RENDERPATH_SOFT:
5215 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5216 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5218 case RENDERPATH_GL20:
5219 case RENDERPATH_GLES2:
5220 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5221 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5227 void R_ResetViewRendering2D(void)
5229 r_viewport_t viewport;
5232 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5233 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);
5234 R_Mesh_ResetRenderTargets();
5235 R_SetViewport(&viewport);
5236 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5237 GL_Color(1, 1, 1, 1);
5238 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5239 GL_BlendFunc(GL_ONE, GL_ZERO);
5240 GL_ScissorTest(false);
5241 GL_DepthMask(false);
5242 GL_DepthRange(0, 1);
5243 GL_DepthTest(false);
5244 GL_DepthFunc(GL_LEQUAL);
5245 R_EntityMatrix(&identitymatrix);
5246 R_Mesh_ResetTextureState();
5247 GL_PolygonOffset(0, 0);
5248 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5249 switch(vid.renderpath)
5251 case RENDERPATH_GL11:
5252 case RENDERPATH_GL13:
5253 case RENDERPATH_GL20:
5254 case RENDERPATH_GLES2:
5255 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5257 case RENDERPATH_D3D9:
5258 case RENDERPATH_D3D10:
5259 case RENDERPATH_D3D11:
5260 case RENDERPATH_SOFT:
5263 GL_CullFace(GL_NONE);
5266 void R_ResetViewRendering3D(void)
5271 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5272 GL_Color(1, 1, 1, 1);
5273 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5274 GL_BlendFunc(GL_ONE, GL_ZERO);
5275 GL_ScissorTest(true);
5277 GL_DepthRange(0, 1);
5279 GL_DepthFunc(GL_LEQUAL);
5280 R_EntityMatrix(&identitymatrix);
5281 R_Mesh_ResetTextureState();
5282 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5283 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5284 switch(vid.renderpath)
5286 case RENDERPATH_GL11:
5287 case RENDERPATH_GL13:
5288 case RENDERPATH_GL20:
5289 case RENDERPATH_GLES2:
5290 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5292 case RENDERPATH_D3D9:
5293 case RENDERPATH_D3D10:
5294 case RENDERPATH_D3D11:
5295 case RENDERPATH_SOFT:
5298 GL_CullFace(r_refdef.view.cullface_back);
5303 R_RenderView_UpdateViewVectors
5306 static void R_RenderView_UpdateViewVectors(void)
5308 // break apart the view matrix into vectors for various purposes
5309 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5310 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5311 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5312 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5313 // make an inverted copy of the view matrix for tracking sprites
5314 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5317 void R_RenderScene(void);
5318 void R_RenderWaterPlanes(void);
5320 static void R_Water_StartFrame(void)
5323 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5324 r_waterstate_waterplane_t *p;
5326 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5329 switch(vid.renderpath)
5331 case RENDERPATH_GL20:
5332 case RENDERPATH_D3D9:
5333 case RENDERPATH_D3D10:
5334 case RENDERPATH_D3D11:
5335 case RENDERPATH_SOFT:
5336 case RENDERPATH_GLES2:
5338 case RENDERPATH_GL13:
5339 case RENDERPATH_GL11:
5343 // set waterwidth and waterheight to the water resolution that will be
5344 // used (often less than the screen resolution for faster rendering)
5345 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5346 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5348 // calculate desired texture sizes
5349 // can't use water if the card does not support the texture size
5350 if (!r_water.integer || r_showsurfaces.integer)
5351 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5352 else if (vid.support.arb_texture_non_power_of_two)
5354 texturewidth = waterwidth;
5355 textureheight = waterheight;
5356 camerawidth = waterwidth;
5357 cameraheight = waterheight;
5361 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5362 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5363 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5364 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5367 // allocate textures as needed
5368 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5370 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5371 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5373 if (p->texture_refraction)
5374 R_FreeTexture(p->texture_refraction);
5375 p->texture_refraction = NULL;
5376 if (p->texture_reflection)
5377 R_FreeTexture(p->texture_reflection);
5378 p->texture_reflection = NULL;
5379 if (p->texture_camera)
5380 R_FreeTexture(p->texture_camera);
5381 p->texture_camera = NULL;
5383 memset(&r_waterstate, 0, sizeof(r_waterstate));
5384 r_waterstate.texturewidth = texturewidth;
5385 r_waterstate.textureheight = textureheight;
5386 r_waterstate.camerawidth = camerawidth;
5387 r_waterstate.cameraheight = cameraheight;
5390 if (r_waterstate.texturewidth)
5392 r_waterstate.enabled = true;
5394 // when doing a reduced render (HDR) we want to use a smaller area
5395 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5396 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5398 // set up variables that will be used in shader setup
5399 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5400 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5401 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5402 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5405 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5406 r_waterstate.numwaterplanes = 0;
5409 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5411 int triangleindex, planeindex;
5417 r_waterstate_waterplane_t *p;
5418 texture_t *t = R_GetCurrentTexture(surface->texture);
5420 // just use the first triangle with a valid normal for any decisions
5421 VectorClear(normal);
5422 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5424 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5425 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5426 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5427 TriangleNormal(vert[0], vert[1], vert[2], normal);
5428 if (VectorLength2(normal) >= 0.001)
5432 VectorCopy(normal, plane.normal);
5433 VectorNormalize(plane.normal);
5434 plane.dist = DotProduct(vert[0], plane.normal);
5435 PlaneClassify(&plane);
5436 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5438 // skip backfaces (except if nocullface is set)
5439 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5441 VectorNegate(plane.normal, plane.normal);
5443 PlaneClassify(&plane);
5447 // find a matching plane if there is one
5448 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5449 if(p->camera_entity == t->camera_entity)
5450 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5452 if (planeindex >= r_waterstate.maxwaterplanes)
5453 return; // nothing we can do, out of planes
5455 // if this triangle does not fit any known plane rendered this frame, add one
5456 if (planeindex >= r_waterstate.numwaterplanes)
5458 // store the new plane
5459 r_waterstate.numwaterplanes++;
5461 // clear materialflags and pvs
5462 p->materialflags = 0;
5463 p->pvsvalid = false;
5464 p->camera_entity = t->camera_entity;
5465 VectorCopy(surface->mins, p->mins);
5466 VectorCopy(surface->maxs, p->maxs);
5471 p->mins[0] = min(p->mins[0], surface->mins[0]);
5472 p->mins[1] = min(p->mins[1], surface->mins[1]);
5473 p->mins[2] = min(p->mins[2], surface->mins[2]);
5474 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5475 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5476 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5478 // merge this surface's materialflags into the waterplane
5479 p->materialflags |= t->currentmaterialflags;
5480 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5482 // merge this surface's PVS into the waterplane
5483 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5484 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5485 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5487 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5493 static void R_Water_ProcessPlanes(void)
5496 r_refdef_view_t originalview;
5497 r_refdef_view_t myview;
5499 r_waterstate_waterplane_t *p;
5502 originalview = r_refdef.view;
5504 // make sure enough textures are allocated
5505 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5507 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5509 if (!p->texture_refraction)
5510 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);
5511 if (!p->texture_refraction)
5514 else if (p->materialflags & MATERIALFLAG_CAMERA)
5516 if (!p->texture_camera)
5517 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);
5518 if (!p->texture_camera)
5522 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5524 if (!p->texture_reflection)
5525 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);
5526 if (!p->texture_reflection)
5532 r_refdef.view = originalview;
5533 r_refdef.view.showdebug = false;
5534 r_refdef.view.width = r_waterstate.waterwidth;
5535 r_refdef.view.height = r_waterstate.waterheight;
5536 r_refdef.view.useclipplane = true;
5537 myview = r_refdef.view;
5538 r_waterstate.renderingscene = true;
5539 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5541 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5543 r_refdef.view = myview;
5544 if(r_water_scissormode.integer)
5547 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5548 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5551 // render reflected scene and copy into texture
5552 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5553 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5554 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5555 r_refdef.view.clipplane = p->plane;
5557 // reverse the cullface settings for this render
5558 r_refdef.view.cullface_front = GL_FRONT;
5559 r_refdef.view.cullface_back = GL_BACK;
5560 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5562 r_refdef.view.usecustompvs = true;
5564 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5566 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5569 R_ResetViewRendering3D();
5570 R_ClearScreen(r_refdef.fogenabled);
5571 if(r_water_scissormode.integer & 2)
5572 R_View_UpdateWithScissor(myscissor);
5575 if(r_water_scissormode.integer & 1)
5576 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5579 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);
5582 // render the normal view scene and copy into texture
5583 // (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)
5584 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5586 r_refdef.view = myview;
5587 if(r_water_scissormode.integer)
5590 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5591 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5594 r_waterstate.renderingrefraction = true;
5596 r_refdef.view.clipplane = p->plane;
5597 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5598 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5600 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5602 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5603 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5604 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5605 R_RenderView_UpdateViewVectors();
5606 if(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);
5613 PlaneClassify(&r_refdef.view.clipplane);
5615 R_ResetViewRendering3D();
5616 R_ClearScreen(r_refdef.fogenabled);
5617 if(r_water_scissormode.integer & 2)
5618 R_View_UpdateWithScissor(myscissor);
5621 if(r_water_scissormode.integer & 1)
5622 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5625 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);
5626 r_waterstate.renderingrefraction = false;
5628 else if (p->materialflags & MATERIALFLAG_CAMERA)
5630 r_refdef.view = myview;
5632 r_refdef.view.clipplane = p->plane;
5633 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5634 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5636 r_refdef.view.width = r_waterstate.camerawidth;
5637 r_refdef.view.height = r_waterstate.cameraheight;
5638 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5639 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5641 if(p->camera_entity)
5643 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5644 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5647 // note: all of the view is used for displaying... so
5648 // there is no use in scissoring
5650 // reverse the cullface settings for this render
5651 r_refdef.view.cullface_front = GL_FRONT;
5652 r_refdef.view.cullface_back = GL_BACK;
5653 // also reverse the view matrix
5654 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
5655 R_RenderView_UpdateViewVectors();
5656 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5658 r_refdef.view.usecustompvs = true;
5659 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);
5662 // camera needs no clipplane
5663 r_refdef.view.useclipplane = false;
5665 PlaneClassify(&r_refdef.view.clipplane);
5667 R_ResetViewRendering3D();
5668 R_ClearScreen(r_refdef.fogenabled);
5672 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);
5673 r_waterstate.renderingrefraction = false;
5677 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5678 r_waterstate.renderingscene = false;
5679 r_refdef.view = originalview;
5680 R_ResetViewRendering3D();
5681 R_ClearScreen(r_refdef.fogenabled);
5685 r_refdef.view = originalview;
5686 r_waterstate.renderingscene = false;
5687 Cvar_SetValueQuick(&r_water, 0);
5688 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5692 void R_Bloom_StartFrame(void)
5694 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5695 int viewwidth, viewheight;
5698 if (r_viewscale_fpsscaling.integer)
5700 double actualframetime;
5701 double targetframetime;
5703 actualframetime = r_refdef.lastdrawscreentime;
5704 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5705 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5706 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5707 if (r_viewscale_fpsscaling_stepsize.value > 0)
5708 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5709 viewscalefpsadjusted += adjust;
5710 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5713 viewscalefpsadjusted = 1.0f;
5715 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5717 switch(vid.renderpath)
5719 case RENDERPATH_GL20:
5720 case RENDERPATH_D3D9:
5721 case RENDERPATH_D3D10:
5722 case RENDERPATH_D3D11:
5723 case RENDERPATH_SOFT:
5724 case RENDERPATH_GLES2:
5726 case RENDERPATH_GL13:
5727 case RENDERPATH_GL11:
5731 // set bloomwidth and bloomheight to the bloom resolution that will be
5732 // used (often less than the screen resolution for faster rendering)
5733 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5734 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5735 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5736 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5737 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5739 // calculate desired texture sizes
5740 if (vid.support.arb_texture_non_power_of_two)
5742 screentexturewidth = vid.width;
5743 screentextureheight = vid.height;
5744 bloomtexturewidth = r_bloomstate.bloomwidth;
5745 bloomtextureheight = r_bloomstate.bloomheight;
5749 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5750 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5751 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5752 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5755 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))
5757 Cvar_SetValueQuick(&r_hdr, 0);
5758 Cvar_SetValueQuick(&r_bloom, 0);
5759 Cvar_SetValueQuick(&r_motionblur, 0);
5760 Cvar_SetValueQuick(&r_damageblur, 0);
5763 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)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5764 screentexturewidth = screentextureheight = 0;
5765 if (!r_hdr.integer && !r_bloom.integer)
5766 bloomtexturewidth = bloomtextureheight = 0;
5768 textype = TEXTYPE_COLORBUFFER;
5769 switch (vid.renderpath)
5771 case RENDERPATH_GL20:
5772 case RENDERPATH_GLES2:
5773 if (vid.support.ext_framebuffer_object)
5775 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5776 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5779 case RENDERPATH_D3D9:
5780 case RENDERPATH_D3D10:
5781 case RENDERPATH_D3D11:
5782 case RENDERPATH_SOFT:
5783 case RENDERPATH_GL13:
5784 case RENDERPATH_GL11:
5788 // allocate textures as needed
5789 if (r_bloomstate.screentexturewidth != screentexturewidth
5790 || r_bloomstate.screentextureheight != screentextureheight
5791 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5792 || r_bloomstate.bloomtextureheight != bloomtextureheight
5793 || r_bloomstate.texturetype != textype
5794 || r_bloomstate.viewfbo != r_viewfbo.integer)
5796 if (r_bloomstate.texture_bloom)
5797 R_FreeTexture(r_bloomstate.texture_bloom);
5798 r_bloomstate.texture_bloom = NULL;
5799 if (r_bloomstate.texture_screen)
5800 R_FreeTexture(r_bloomstate.texture_screen);
5801 r_bloomstate.texture_screen = NULL;
5802 if (r_bloomstate.fbo_framebuffer)
5803 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5804 r_bloomstate.fbo_framebuffer = 0;
5805 if (r_bloomstate.texture_framebuffercolor)
5806 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5807 r_bloomstate.texture_framebuffercolor = NULL;
5808 if (r_bloomstate.texture_framebufferdepth)
5809 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5810 r_bloomstate.texture_framebufferdepth = NULL;
5811 r_bloomstate.screentexturewidth = screentexturewidth;
5812 r_bloomstate.screentextureheight = screentextureheight;
5813 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5814 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5815 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5817 // FIXME: choose depth bits based on a cvar
5818 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5819 r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5820 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5821 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5822 // render depth into one texture and normalmap into the other
5826 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5827 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5828 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5829 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5830 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5833 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5834 r_bloomstate.bloomtextureheight = bloomtextureheight;
5835 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5836 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5837 r_bloomstate.viewfbo = r_viewfbo.integer;
5838 r_bloomstate.texturetype = textype;
5841 // when doing a reduced render (HDR) we want to use a smaller area
5842 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5843 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5844 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5845 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5846 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5848 // set up a texcoord array for the full resolution screen image
5849 // (we have to keep this around to copy back during final render)
5850 r_bloomstate.screentexcoord2f[0] = 0;
5851 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5852 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5853 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5854 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5855 r_bloomstate.screentexcoord2f[5] = 0;
5856 r_bloomstate.screentexcoord2f[6] = 0;
5857 r_bloomstate.screentexcoord2f[7] = 0;
5859 // set up a texcoord array for the reduced resolution bloom image
5860 // (which will be additive blended over the screen image)
5861 r_bloomstate.bloomtexcoord2f[0] = 0;
5862 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5863 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5864 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5865 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5866 r_bloomstate.bloomtexcoord2f[5] = 0;
5867 r_bloomstate.bloomtexcoord2f[6] = 0;
5868 r_bloomstate.bloomtexcoord2f[7] = 0;
5870 switch(vid.renderpath)
5872 case RENDERPATH_GL11:
5873 case RENDERPATH_GL13:
5874 case RENDERPATH_GL20:
5875 case RENDERPATH_SOFT:
5876 case RENDERPATH_GLES2:
5878 case RENDERPATH_D3D9:
5879 case RENDERPATH_D3D10:
5880 case RENDERPATH_D3D11:
5883 for (i = 0;i < 4;i++)
5885 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5886 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5887 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5888 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5894 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5896 r_bloomstate.enabled = true;
5897 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5900 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);
5902 if (r_bloomstate.fbo_framebuffer)
5903 r_refdef.view.clear = true;
5906 void R_Bloom_CopyBloomTexture(float colorscale)
5908 r_refdef.stats.bloom++;
5910 // scale down screen texture to the bloom texture size
5912 R_Mesh_SetMainRenderTargets();
5913 R_SetViewport(&r_bloomstate.viewport);
5914 GL_BlendFunc(GL_ONE, GL_ZERO);
5915 GL_Color(colorscale, colorscale, colorscale, 1);
5916 // 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...
5917 switch(vid.renderpath)
5919 case RENDERPATH_GL11:
5920 case RENDERPATH_GL13:
5921 case RENDERPATH_GL20:
5922 case RENDERPATH_SOFT:
5923 case RENDERPATH_GLES2:
5924 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5926 case RENDERPATH_D3D9:
5927 case RENDERPATH_D3D10:
5928 case RENDERPATH_D3D11:
5929 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5932 // TODO: do boxfilter scale-down in shader?
5933 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5934 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5935 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5937 // we now have a bloom image in the framebuffer
5938 // copy it into the bloom image texture for later processing
5939 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);
5940 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5943 void R_Bloom_CopyHDRTexture(void)
5945 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);
5946 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5949 void R_Bloom_MakeTexture(void)
5952 float xoffset, yoffset, r, brighten;
5954 r_refdef.stats.bloom++;
5956 R_ResetViewRendering2D();
5958 // we have a bloom image in the framebuffer
5960 R_SetViewport(&r_bloomstate.viewport);
5962 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5965 r = bound(0, r_bloom_colorexponent.value / x, 1);
5966 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5968 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5969 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5970 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5971 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5973 // copy the vertically blurred bloom view to a texture
5974 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);
5975 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5978 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5979 brighten = r_bloom_brighten.value;
5980 if (r_bloomstate.hdr)
5981 brighten *= r_hdr_range.value;
5982 brighten = sqrt(brighten);
5984 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5985 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5987 for (dir = 0;dir < 2;dir++)
5989 // blend on at multiple vertical offsets to achieve a vertical blur
5990 // TODO: do offset blends using GLSL
5991 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5992 GL_BlendFunc(GL_ONE, GL_ZERO);
5993 for (x = -range;x <= range;x++)
5995 if (!dir){xoffset = 0;yoffset = x;}
5996 else {xoffset = x;yoffset = 0;}
5997 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5998 yoffset /= (float)r_bloomstate.bloomtextureheight;
5999 // compute a texcoord array with the specified x and y offset
6000 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6001 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6002 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6003 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6004 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6005 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6006 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6007 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6008 // this r value looks like a 'dot' particle, fading sharply to
6009 // black at the edges
6010 // (probably not realistic but looks good enough)
6011 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6012 //r = brighten/(range*2+1);
6013 r = brighten / (range * 2 + 1);
6015 r *= (1 - x*x/(float)(range*range));
6016 GL_Color(r, r, r, 1);
6017 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6018 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6019 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6020 GL_BlendFunc(GL_ONE, GL_ONE);
6023 // copy the vertically blurred bloom view to a texture
6024 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);
6025 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6029 void R_HDR_RenderBloomTexture(void)
6031 int oldwidth, oldheight;
6032 float oldcolorscale;
6033 qboolean oldwaterstate;
6035 oldwaterstate = r_waterstate.enabled;
6036 oldcolorscale = r_refdef.view.colorscale;
6037 oldwidth = r_refdef.view.width;
6038 oldheight = r_refdef.view.height;
6039 r_refdef.view.width = r_bloomstate.bloomwidth;
6040 r_refdef.view.height = r_bloomstate.bloomheight;
6042 if(r_hdr.integer < 2)
6043 r_waterstate.enabled = false;
6045 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6046 // TODO: add exposure compensation features
6047 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6049 r_refdef.view.showdebug = false;
6050 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6052 R_ResetViewRendering3D();
6054 R_ClearScreen(r_refdef.fogenabled);
6055 if (r_timereport_active)
6056 R_TimeReport("HDRclear");
6059 if (r_timereport_active)
6060 R_TimeReport("visibility");
6062 // only do secondary renders with HDR if r_hdr is 2 or higher
6063 r_waterstate.numwaterplanes = 0;
6064 if (r_waterstate.enabled)
6065 R_RenderWaterPlanes();
6067 r_refdef.view.showdebug = true;
6069 r_waterstate.numwaterplanes = 0;
6071 R_ResetViewRendering2D();
6073 R_Bloom_CopyHDRTexture();
6074 R_Bloom_MakeTexture();
6076 // restore the view settings
6077 r_waterstate.enabled = oldwaterstate;
6078 r_refdef.view.width = oldwidth;
6079 r_refdef.view.height = oldheight;
6080 r_refdef.view.colorscale = oldcolorscale;
6082 R_ResetViewRendering3D();
6084 R_ClearScreen(r_refdef.fogenabled);
6085 if (r_timereport_active)
6086 R_TimeReport("viewclear");
6089 static void R_BlendView(void)
6091 unsigned int permutation;
6092 float uservecs[4][4];
6094 switch (vid.renderpath)
6096 case RENDERPATH_GL20:
6097 case RENDERPATH_D3D9:
6098 case RENDERPATH_D3D10:
6099 case RENDERPATH_D3D11:
6100 case RENDERPATH_SOFT:
6101 case RENDERPATH_GLES2:
6103 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6104 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6105 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6106 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6107 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6109 if (r_bloomstate.texture_screen)
6111 // make sure the buffer is available
6112 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6114 R_ResetViewRendering2D();
6115 R_Mesh_SetMainRenderTargets();
6117 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6119 // declare variables
6121 static float avgspeed;
6123 speed = VectorLength(cl.movement_velocity);
6125 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6126 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6128 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6129 speed = bound(0, speed, 1);
6130 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6132 // calculate values into a standard alpha
6133 cl.motionbluralpha = 1 - exp(-
6135 (r_motionblur.value * speed / 80)
6137 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6140 max(0.0001, cl.time - cl.oldtime) // fps independent
6143 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6144 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6146 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6148 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6149 GL_Color(1, 1, 1, cl.motionbluralpha);
6150 switch(vid.renderpath)
6152 case RENDERPATH_GL11:
6153 case RENDERPATH_GL13:
6154 case RENDERPATH_GL20:
6155 case RENDERPATH_SOFT:
6156 case RENDERPATH_GLES2:
6157 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6159 case RENDERPATH_D3D9:
6160 case RENDERPATH_D3D10:
6161 case RENDERPATH_D3D11:
6162 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6165 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6166 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6167 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6171 // copy view into the screen texture
6172 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);
6173 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6175 else if (!r_bloomstate.texture_bloom)
6177 // we may still have to do view tint...
6178 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6180 // apply a color tint to the whole view
6181 R_ResetViewRendering2D();
6182 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6183 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6184 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6185 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6186 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6188 break; // no screen processing, no bloom, skip it
6191 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6193 // render simple bloom effect
6194 // copy the screen and shrink it and darken it for the bloom process
6195 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6196 // make the bloom texture
6197 R_Bloom_MakeTexture();
6200 #if _MSC_VER >= 1400
6201 #define sscanf sscanf_s
6203 memset(uservecs, 0, sizeof(uservecs));
6204 if (r_glsl_postprocess_uservec1_enable.integer)
6205 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6206 if (r_glsl_postprocess_uservec2_enable.integer)
6207 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6208 if (r_glsl_postprocess_uservec3_enable.integer)
6209 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6210 if (r_glsl_postprocess_uservec4_enable.integer)
6211 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6213 R_ResetViewRendering2D();
6214 GL_Color(1, 1, 1, 1);
6215 GL_BlendFunc(GL_ONE, GL_ZERO);
6217 switch(vid.renderpath)
6219 case RENDERPATH_GL20:
6220 case RENDERPATH_GLES2:
6221 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6222 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6223 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6224 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6225 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6226 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]);
6227 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6228 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]);
6229 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]);
6230 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]);
6231 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]);
6232 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6233 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6234 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);
6236 case RENDERPATH_D3D9:
6238 // 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...
6239 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6240 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6241 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6242 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6243 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6244 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6245 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6246 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6247 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6248 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6249 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6250 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6251 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6252 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6255 case RENDERPATH_D3D10:
6256 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6258 case RENDERPATH_D3D11:
6259 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6261 case RENDERPATH_SOFT:
6262 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6263 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6264 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6265 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6266 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6267 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6268 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6269 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6270 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6271 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6272 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6273 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6274 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6275 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6280 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6281 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6283 case RENDERPATH_GL13:
6284 case RENDERPATH_GL11:
6285 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6287 // apply a color tint to the whole view
6288 R_ResetViewRendering2D();
6289 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6290 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6291 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6292 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6293 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6299 matrix4x4_t r_waterscrollmatrix;
6301 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6303 if (r_refdef.fog_density)
6305 r_refdef.fogcolor[0] = r_refdef.fog_red;
6306 r_refdef.fogcolor[1] = r_refdef.fog_green;
6307 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6309 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6310 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6311 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6312 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6316 VectorCopy(r_refdef.fogcolor, fogvec);
6317 // color.rgb *= ContrastBoost * SceneBrightness;
6318 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6319 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6320 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6321 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6326 void R_UpdateVariables(void)
6330 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6332 r_refdef.farclip = r_farclip_base.value;
6333 if (r_refdef.scene.worldmodel)
6334 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6335 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6337 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6338 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6339 r_refdef.polygonfactor = 0;
6340 r_refdef.polygonoffset = 0;
6341 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6342 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6344 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6345 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6346 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6347 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6348 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6349 if (FAKELIGHT_ENABLED)
6351 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6353 if (r_showsurfaces.integer)
6355 r_refdef.scene.rtworld = false;
6356 r_refdef.scene.rtworldshadows = false;
6357 r_refdef.scene.rtdlight = false;
6358 r_refdef.scene.rtdlightshadows = false;
6359 r_refdef.lightmapintensity = 0;
6362 if (gamemode == GAME_NEHAHRA)
6364 if (gl_fogenable.integer)
6366 r_refdef.oldgl_fogenable = true;
6367 r_refdef.fog_density = gl_fogdensity.value;
6368 r_refdef.fog_red = gl_fogred.value;
6369 r_refdef.fog_green = gl_foggreen.value;
6370 r_refdef.fog_blue = gl_fogblue.value;
6371 r_refdef.fog_alpha = 1;
6372 r_refdef.fog_start = 0;
6373 r_refdef.fog_end = gl_skyclip.value;
6374 r_refdef.fog_height = 1<<30;
6375 r_refdef.fog_fadedepth = 128;
6377 else if (r_refdef.oldgl_fogenable)
6379 r_refdef.oldgl_fogenable = false;
6380 r_refdef.fog_density = 0;
6381 r_refdef.fog_red = 0;
6382 r_refdef.fog_green = 0;
6383 r_refdef.fog_blue = 0;
6384 r_refdef.fog_alpha = 0;
6385 r_refdef.fog_start = 0;
6386 r_refdef.fog_end = 0;
6387 r_refdef.fog_height = 1<<30;
6388 r_refdef.fog_fadedepth = 128;
6392 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6393 r_refdef.fog_start = max(0, r_refdef.fog_start);
6394 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6396 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6398 if (r_refdef.fog_density && r_drawfog.integer)
6400 r_refdef.fogenabled = true;
6401 // this is the point where the fog reaches 0.9986 alpha, which we
6402 // consider a good enough cutoff point for the texture
6403 // (0.9986 * 256 == 255.6)
6404 if (r_fog_exp2.integer)
6405 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6407 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6408 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6409 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6410 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6411 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6412 R_BuildFogHeightTexture();
6413 // fog color was already set
6414 // update the fog texture
6415 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)
6416 R_BuildFogTexture();
6417 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6418 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6421 r_refdef.fogenabled = false;
6423 switch(vid.renderpath)
6425 case RENDERPATH_GL20:
6426 case RENDERPATH_D3D9:
6427 case RENDERPATH_D3D10:
6428 case RENDERPATH_D3D11:
6429 case RENDERPATH_SOFT:
6430 case RENDERPATH_GLES2:
6431 if(v_glslgamma.integer && !vid_gammatables_trivial)
6433 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6435 // build GLSL gamma texture
6436 #define RAMPWIDTH 256
6437 unsigned short ramp[RAMPWIDTH * 3];
6438 unsigned char rampbgr[RAMPWIDTH][4];
6441 r_texture_gammaramps_serial = vid_gammatables_serial;
6443 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6444 for(i = 0; i < RAMPWIDTH; ++i)
6446 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6447 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6448 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6451 if (r_texture_gammaramps)
6453 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6457 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6463 // remove GLSL gamma texture
6466 case RENDERPATH_GL13:
6467 case RENDERPATH_GL11:
6472 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6473 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6479 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6480 if( scenetype != r_currentscenetype ) {
6481 // store the old scenetype
6482 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6483 r_currentscenetype = scenetype;
6484 // move in the new scene
6485 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6494 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6496 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6497 if( scenetype == r_currentscenetype ) {
6498 return &r_refdef.scene;
6500 return &r_scenes_store[ scenetype ];
6509 int dpsoftrast_test;
6510 void R_RenderView(void)
6512 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6514 dpsoftrast_test = r_test.integer;
6516 if (r_timereport_active)
6517 R_TimeReport("start");
6518 r_textureframe++; // used only by R_GetCurrentTexture
6519 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6521 if(R_CompileShader_CheckStaticParms())
6524 if (!r_drawentities.integer)
6525 r_refdef.scene.numentities = 0;
6527 R_AnimCache_ClearCache();
6528 R_FrameData_NewFrame();
6530 /* adjust for stereo display */
6531 if(R_Stereo_Active())
6533 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);
6534 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6537 if (r_refdef.view.isoverlay)
6539 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6540 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6541 R_TimeReport("depthclear");
6543 r_refdef.view.showdebug = false;
6545 r_waterstate.enabled = false;
6546 r_waterstate.numwaterplanes = 0;
6550 r_refdef.view.matrix = originalmatrix;
6556 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6558 r_refdef.view.matrix = originalmatrix;
6559 return; //Host_Error ("R_RenderView: NULL worldmodel");
6562 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6564 R_RenderView_UpdateViewVectors();
6566 R_Shadow_UpdateWorldLightSelection();
6568 R_Bloom_StartFrame();
6569 R_Water_StartFrame();
6572 if (r_timereport_active)
6573 R_TimeReport("viewsetup");
6575 R_ResetViewRendering3D();
6577 if (r_refdef.view.clear || r_refdef.fogenabled)
6579 R_ClearScreen(r_refdef.fogenabled);
6580 if (r_timereport_active)
6581 R_TimeReport("viewclear");
6583 r_refdef.view.clear = true;
6585 // this produces a bloom texture to be used in R_BlendView() later
6586 if (r_bloomstate.hdr)
6588 R_HDR_RenderBloomTexture();
6589 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6590 r_textureframe++; // used only by R_GetCurrentTexture
6593 r_refdef.view.showdebug = true;
6596 if (r_timereport_active)
6597 R_TimeReport("visibility");
6599 r_waterstate.numwaterplanes = 0;
6600 if (r_waterstate.enabled)
6601 R_RenderWaterPlanes();
6604 r_waterstate.numwaterplanes = 0;
6607 if (r_timereport_active)
6608 R_TimeReport("blendview");
6610 GL_Scissor(0, 0, vid.width, vid.height);
6611 GL_ScissorTest(false);
6613 r_refdef.view.matrix = originalmatrix;
6618 void R_RenderWaterPlanes(void)
6620 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6622 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6623 if (r_timereport_active)
6624 R_TimeReport("waterworld");
6627 // don't let sound skip if going slow
6628 if (r_refdef.scene.extraupdate)
6631 R_DrawModelsAddWaterPlanes();
6632 if (r_timereport_active)
6633 R_TimeReport("watermodels");
6635 if (r_waterstate.numwaterplanes)
6637 R_Water_ProcessPlanes();
6638 if (r_timereport_active)
6639 R_TimeReport("waterscenes");
6643 extern void R_DrawLightningBeams (void);
6644 extern void VM_CL_AddPolygonsToMeshQueue (void);
6645 extern void R_DrawPortals (void);
6646 extern cvar_t cl_locs_show;
6647 static void R_DrawLocs(void);
6648 static void R_DrawEntityBBoxes(void);
6649 static void R_DrawModelDecals(void);
6650 extern void R_DrawModelShadows(void);
6651 extern void R_DrawModelShadowMaps(void);
6652 extern cvar_t cl_decals_newsystem;
6653 extern qboolean r_shadow_usingdeferredprepass;
6654 void R_RenderScene(void)
6656 qboolean shadowmapping = false;
6658 if (r_timereport_active)
6659 R_TimeReport("beginscene");
6661 r_refdef.stats.renders++;
6665 // don't let sound skip if going slow
6666 if (r_refdef.scene.extraupdate)
6669 R_MeshQueue_BeginScene();
6673 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);
6675 if (r_timereport_active)
6676 R_TimeReport("skystartframe");
6678 if (cl.csqc_vidvars.drawworld)
6680 // don't let sound skip if going slow
6681 if (r_refdef.scene.extraupdate)
6684 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6686 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6687 if (r_timereport_active)
6688 R_TimeReport("worldsky");
6691 if (R_DrawBrushModelsSky() && r_timereport_active)
6692 R_TimeReport("bmodelsky");
6694 if (skyrendermasked && skyrenderlater)
6696 // we have to force off the water clipping plane while rendering sky
6700 if (r_timereport_active)
6701 R_TimeReport("sky");
6705 R_AnimCache_CacheVisibleEntities();
6706 if (r_timereport_active)
6707 R_TimeReport("animation");
6709 R_Shadow_PrepareLights();
6710 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6711 R_Shadow_PrepareModelShadows();
6712 if (r_timereport_active)
6713 R_TimeReport("preparelights");
6715 if (R_Shadow_ShadowMappingEnabled())
6716 shadowmapping = true;
6718 if (r_shadow_usingdeferredprepass)
6719 R_Shadow_DrawPrepass();
6721 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6723 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6724 if (r_timereport_active)
6725 R_TimeReport("worlddepth");
6727 if (r_depthfirst.integer >= 2)
6729 R_DrawModelsDepth();
6730 if (r_timereport_active)
6731 R_TimeReport("modeldepth");
6734 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6736 R_DrawModelShadowMaps();
6737 R_ResetViewRendering3D();
6738 // don't let sound skip if going slow
6739 if (r_refdef.scene.extraupdate)
6743 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6745 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6746 if (r_timereport_active)
6747 R_TimeReport("world");
6750 // don't let sound skip if going slow
6751 if (r_refdef.scene.extraupdate)
6755 if (r_timereport_active)
6756 R_TimeReport("models");
6758 // don't let sound skip if going slow
6759 if (r_refdef.scene.extraupdate)
6762 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6764 R_DrawModelShadows();
6765 R_ResetViewRendering3D();
6766 // don't let sound skip if going slow
6767 if (r_refdef.scene.extraupdate)
6771 if (!r_shadow_usingdeferredprepass)
6773 R_Shadow_DrawLights();
6774 if (r_timereport_active)
6775 R_TimeReport("rtlights");
6778 // don't let sound skip if going slow
6779 if (r_refdef.scene.extraupdate)
6782 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6784 R_DrawModelShadows();
6785 R_ResetViewRendering3D();
6786 // don't let sound skip if going slow
6787 if (r_refdef.scene.extraupdate)
6791 if (cl.csqc_vidvars.drawworld)
6793 if (cl_decals_newsystem.integer)
6795 R_DrawModelDecals();
6796 if (r_timereport_active)
6797 R_TimeReport("modeldecals");
6802 if (r_timereport_active)
6803 R_TimeReport("decals");
6807 if (r_timereport_active)
6808 R_TimeReport("particles");
6811 if (r_timereport_active)
6812 R_TimeReport("explosions");
6814 R_DrawLightningBeams();
6815 if (r_timereport_active)
6816 R_TimeReport("lightning");
6819 VM_CL_AddPolygonsToMeshQueue();
6821 if (r_refdef.view.showdebug)
6823 if (cl_locs_show.integer)
6826 if (r_timereport_active)
6827 R_TimeReport("showlocs");
6830 if (r_drawportals.integer)
6833 if (r_timereport_active)
6834 R_TimeReport("portals");
6837 if (r_showbboxes.value > 0)
6839 R_DrawEntityBBoxes();
6840 if (r_timereport_active)
6841 R_TimeReport("bboxes");
6845 R_MeshQueue_RenderTransparent();
6846 if (r_timereport_active)
6847 R_TimeReport("drawtrans");
6849 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))
6851 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6852 if (r_timereport_active)
6853 R_TimeReport("worlddebug");
6854 R_DrawModelsDebug();
6855 if (r_timereport_active)
6856 R_TimeReport("modeldebug");
6859 if (cl.csqc_vidvars.drawworld)
6861 R_Shadow_DrawCoronas();
6862 if (r_timereport_active)
6863 R_TimeReport("coronas");
6868 GL_DepthTest(false);
6869 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6870 GL_Color(1, 1, 1, 1);
6871 qglBegin(GL_POLYGON);
6872 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6873 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6874 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6875 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6877 qglBegin(GL_POLYGON);
6878 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]);
6879 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]);
6880 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]);
6881 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]);
6883 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6887 // don't let sound skip if going slow
6888 if (r_refdef.scene.extraupdate)
6891 R_ResetViewRendering2D();
6894 static const unsigned short bboxelements[36] =
6904 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6907 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6909 RSurf_ActiveWorldEntity();
6911 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6912 GL_DepthMask(false);
6913 GL_DepthRange(0, 1);
6914 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6915 // R_Mesh_ResetTextureState();
6917 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6918 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6919 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6920 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6921 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6922 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6923 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6924 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6925 R_FillColors(color4f, 8, cr, cg, cb, ca);
6926 if (r_refdef.fogenabled)
6928 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6930 f1 = RSurf_FogVertex(v);
6932 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6933 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6934 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6937 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6938 R_Mesh_ResetTextureState();
6939 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6940 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6943 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6947 prvm_edict_t *edict;
6948 prvm_prog_t *prog_save = prog;
6950 // this function draws bounding boxes of server entities
6954 GL_CullFace(GL_NONE);
6955 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6959 for (i = 0;i < numsurfaces;i++)
6961 edict = PRVM_EDICT_NUM(surfacelist[i]);
6962 switch ((int)edict->fields.server->solid)
6964 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6965 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6966 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6967 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6968 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6969 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6971 color[3] *= r_showbboxes.value;
6972 color[3] = bound(0, color[3], 1);
6973 GL_DepthTest(!r_showdisabledepthtest.integer);
6974 GL_CullFace(r_refdef.view.cullface_front);
6975 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6981 static void R_DrawEntityBBoxes(void)
6984 prvm_edict_t *edict;
6986 prvm_prog_t *prog_save = prog;
6988 // this function draws bounding boxes of server entities
6994 for (i = 0;i < prog->num_edicts;i++)
6996 edict = PRVM_EDICT_NUM(i);
6997 if (edict->priv.server->free)
6999 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7000 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7002 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7004 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7005 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7011 static const int nomodelelement3i[24] =
7023 static const unsigned short nomodelelement3s[24] =
7035 static const float nomodelvertex3f[6*3] =
7045 static const float nomodelcolor4f[6*4] =
7047 0.0f, 0.0f, 0.5f, 1.0f,
7048 0.0f, 0.0f, 0.5f, 1.0f,
7049 0.0f, 0.5f, 0.0f, 1.0f,
7050 0.0f, 0.5f, 0.0f, 1.0f,
7051 0.5f, 0.0f, 0.0f, 1.0f,
7052 0.5f, 0.0f, 0.0f, 1.0f
7055 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7061 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);
7063 // this is only called once per entity so numsurfaces is always 1, and
7064 // surfacelist is always {0}, so this code does not handle batches
7066 if (rsurface.ent_flags & RENDER_ADDITIVE)
7068 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7069 GL_DepthMask(false);
7071 else if (rsurface.colormod[3] < 1)
7073 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7074 GL_DepthMask(false);
7078 GL_BlendFunc(GL_ONE, GL_ZERO);
7081 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7082 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7083 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7084 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7085 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7086 for (i = 0, c = color4f;i < 6;i++, c += 4)
7088 c[0] *= rsurface.colormod[0];
7089 c[1] *= rsurface.colormod[1];
7090 c[2] *= rsurface.colormod[2];
7091 c[3] *= rsurface.colormod[3];
7093 if (r_refdef.fogenabled)
7095 for (i = 0, c = color4f;i < 6;i++, c += 4)
7097 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7099 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7100 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7101 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7104 // R_Mesh_ResetTextureState();
7105 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7106 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7107 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7110 void R_DrawNoModel(entity_render_t *ent)
7113 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7114 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7115 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7117 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7120 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7122 vec3_t right1, right2, diff, normal;
7124 VectorSubtract (org2, org1, normal);
7126 // calculate 'right' vector for start
7127 VectorSubtract (r_refdef.view.origin, org1, diff);
7128 CrossProduct (normal, diff, right1);
7129 VectorNormalize (right1);
7131 // calculate 'right' vector for end
7132 VectorSubtract (r_refdef.view.origin, org2, diff);
7133 CrossProduct (normal, diff, right2);
7134 VectorNormalize (right2);
7136 vert[ 0] = org1[0] + width * right1[0];
7137 vert[ 1] = org1[1] + width * right1[1];
7138 vert[ 2] = org1[2] + width * right1[2];
7139 vert[ 3] = org1[0] - width * right1[0];
7140 vert[ 4] = org1[1] - width * right1[1];
7141 vert[ 5] = org1[2] - width * right1[2];
7142 vert[ 6] = org2[0] - width * right2[0];
7143 vert[ 7] = org2[1] - width * right2[1];
7144 vert[ 8] = org2[2] - width * right2[2];
7145 vert[ 9] = org2[0] + width * right2[0];
7146 vert[10] = org2[1] + width * right2[1];
7147 vert[11] = org2[2] + width * right2[2];
7150 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)
7152 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7153 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7154 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7155 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7156 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7157 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7158 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7159 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7160 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7161 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7162 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7163 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7166 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7171 VectorSet(v, x, y, z);
7172 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7173 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7175 if (i == mesh->numvertices)
7177 if (mesh->numvertices < mesh->maxvertices)
7179 VectorCopy(v, vertex3f);
7180 mesh->numvertices++;
7182 return mesh->numvertices;
7188 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7192 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7193 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7194 e = mesh->element3i + mesh->numtriangles * 3;
7195 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7197 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7198 if (mesh->numtriangles < mesh->maxtriangles)
7203 mesh->numtriangles++;
7205 element[1] = element[2];
7209 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7213 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7214 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7215 e = mesh->element3i + mesh->numtriangles * 3;
7216 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7218 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7219 if (mesh->numtriangles < mesh->maxtriangles)
7224 mesh->numtriangles++;
7226 element[1] = element[2];
7230 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7231 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7233 int planenum, planenum2;
7236 mplane_t *plane, *plane2;
7238 double temppoints[2][256*3];
7239 // figure out how large a bounding box we need to properly compute this brush
7241 for (w = 0;w < numplanes;w++)
7242 maxdist = max(maxdist, fabs(planes[w].dist));
7243 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7244 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7245 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7249 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7250 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7252 if (planenum2 == planenum)
7254 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);
7257 if (tempnumpoints < 3)
7259 // generate elements forming a triangle fan for this polygon
7260 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7264 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)
7266 texturelayer_t *layer;
7267 layer = t->currentlayers + t->currentnumlayers++;
7269 layer->depthmask = depthmask;
7270 layer->blendfunc1 = blendfunc1;
7271 layer->blendfunc2 = blendfunc2;
7272 layer->texture = texture;
7273 layer->texmatrix = *matrix;
7274 layer->color[0] = r;
7275 layer->color[1] = g;
7276 layer->color[2] = b;
7277 layer->color[3] = a;
7280 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7282 if(parms[0] == 0 && parms[1] == 0)
7284 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7285 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7290 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7293 index = parms[2] + r_refdef.scene.time * parms[3];
7294 index -= floor(index);
7295 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7298 case Q3WAVEFUNC_NONE:
7299 case Q3WAVEFUNC_NOISE:
7300 case Q3WAVEFUNC_COUNT:
7303 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7304 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7305 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7306 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7307 case Q3WAVEFUNC_TRIANGLE:
7309 f = index - floor(index);
7320 f = parms[0] + parms[1] * f;
7321 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7322 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7326 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7331 matrix4x4_t matrix, temp;
7332 switch(tcmod->tcmod)
7336 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7337 matrix = r_waterscrollmatrix;
7339 matrix = identitymatrix;
7341 case Q3TCMOD_ENTITYTRANSLATE:
7342 // this is used in Q3 to allow the gamecode to control texcoord
7343 // scrolling on the entity, which is not supported in darkplaces yet.
7344 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7346 case Q3TCMOD_ROTATE:
7347 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7348 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7349 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7352 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7354 case Q3TCMOD_SCROLL:
7355 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7357 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7358 w = (int) tcmod->parms[0];
7359 h = (int) tcmod->parms[1];
7360 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7362 idx = (int) floor(f * w * h);
7363 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7365 case Q3TCMOD_STRETCH:
7366 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7367 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7369 case Q3TCMOD_TRANSFORM:
7370 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7371 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7372 VectorSet(tcmat + 6, 0 , 0 , 1);
7373 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7374 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7376 case Q3TCMOD_TURBULENT:
7377 // this is handled in the RSurf_PrepareVertices function
7378 matrix = identitymatrix;
7382 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7385 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7387 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7388 char name[MAX_QPATH];
7389 skinframe_t *skinframe;
7390 unsigned char pixels[296*194];
7391 strlcpy(cache->name, skinname, sizeof(cache->name));
7392 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7393 if (developer_loading.integer)
7394 Con_Printf("loading %s\n", name);
7395 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7396 if (!skinframe || !skinframe->base)
7399 fs_offset_t filesize;
7401 f = FS_LoadFile(name, tempmempool, true, &filesize);
7404 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7405 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7409 cache->skinframe = skinframe;
7412 texture_t *R_GetCurrentTexture(texture_t *t)
7415 const entity_render_t *ent = rsurface.entity;
7416 dp_model_t *model = ent->model;
7417 q3shaderinfo_layer_tcmod_t *tcmod;
7419 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7420 return t->currentframe;
7421 t->update_lastrenderframe = r_textureframe;
7422 t->update_lastrenderentity = (void *)ent;
7424 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7425 t->camera_entity = ent->entitynumber;
7427 t->camera_entity = 0;
7429 // switch to an alternate material if this is a q1bsp animated material
7431 texture_t *texture = t;
7432 int s = rsurface.ent_skinnum;
7433 if ((unsigned int)s >= (unsigned int)model->numskins)
7435 if (model->skinscenes)
7437 if (model->skinscenes[s].framecount > 1)
7438 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7440 s = model->skinscenes[s].firstframe;
7443 t = t + s * model->num_surfaces;
7446 // use an alternate animation if the entity's frame is not 0,
7447 // and only if the texture has an alternate animation
7448 if (rsurface.ent_alttextures && t->anim_total[1])
7449 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7451 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7453 texture->currentframe = t;
7456 // update currentskinframe to be a qw skin or animation frame
7457 if (rsurface.ent_qwskin >= 0)
7459 i = rsurface.ent_qwskin;
7460 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7462 r_qwskincache_size = cl.maxclients;
7464 Mem_Free(r_qwskincache);
7465 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7467 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7468 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7469 t->currentskinframe = r_qwskincache[i].skinframe;
7470 if (t->currentskinframe == NULL)
7471 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7473 else if (t->numskinframes >= 2)
7474 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7475 if (t->backgroundnumskinframes >= 2)
7476 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7478 t->currentmaterialflags = t->basematerialflags;
7479 t->currentalpha = rsurface.colormod[3];
7480 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7481 t->currentalpha *= r_wateralpha.value;
7482 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7483 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7484 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7485 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7486 if (!(rsurface.ent_flags & RENDER_LIGHT))
7487 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7488 else if (FAKELIGHT_ENABLED)
7490 // no modellight if using fakelight for the map
7492 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7494 // pick a model lighting mode
7495 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7496 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7498 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7500 if (rsurface.ent_flags & RENDER_ADDITIVE)
7501 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7502 else if (t->currentalpha < 1)
7503 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7504 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7505 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7506 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7507 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7508 if (t->backgroundnumskinframes)
7509 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7510 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7512 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7513 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7516 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7517 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7518 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7520 // there is no tcmod
7521 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7523 t->currenttexmatrix = r_waterscrollmatrix;
7524 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7526 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7528 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7529 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7532 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7533 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7534 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7535 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7537 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7538 if (t->currentskinframe->qpixels)
7539 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7540 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7541 if (!t->basetexture)
7542 t->basetexture = r_texture_notexture;
7543 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7544 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7545 t->nmaptexture = t->currentskinframe->nmap;
7546 if (!t->nmaptexture)
7547 t->nmaptexture = r_texture_blanknormalmap;
7548 t->glosstexture = r_texture_black;
7549 t->glowtexture = t->currentskinframe->glow;
7550 t->fogtexture = t->currentskinframe->fog;
7551 t->reflectmasktexture = t->currentskinframe->reflect;
7552 if (t->backgroundnumskinframes)
7554 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7555 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7556 t->backgroundglosstexture = r_texture_black;
7557 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7558 if (!t->backgroundnmaptexture)
7559 t->backgroundnmaptexture = r_texture_blanknormalmap;
7563 t->backgroundbasetexture = r_texture_white;
7564 t->backgroundnmaptexture = r_texture_blanknormalmap;
7565 t->backgroundglosstexture = r_texture_black;
7566 t->backgroundglowtexture = NULL;
7568 t->specularpower = r_shadow_glossexponent.value;
7569 // TODO: store reference values for these in the texture?
7570 t->specularscale = 0;
7571 if (r_shadow_gloss.integer > 0)
7573 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7575 if (r_shadow_glossintensity.value > 0)
7577 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7578 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7579 t->specularscale = r_shadow_glossintensity.value;
7582 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7584 t->glosstexture = r_texture_white;
7585 t->backgroundglosstexture = r_texture_white;
7586 t->specularscale = r_shadow_gloss2intensity.value;
7587 t->specularpower = r_shadow_gloss2exponent.value;
7590 t->specularscale *= t->specularscalemod;
7591 t->specularpower *= t->specularpowermod;
7593 // lightmaps mode looks bad with dlights using actual texturing, so turn
7594 // off the colormap and glossmap, but leave the normalmap on as it still
7595 // accurately represents the shading involved
7596 if (gl_lightmaps.integer)
7598 t->basetexture = r_texture_grey128;
7599 t->pantstexture = r_texture_black;
7600 t->shirttexture = r_texture_black;
7601 t->nmaptexture = r_texture_blanknormalmap;
7602 t->glosstexture = r_texture_black;
7603 t->glowtexture = NULL;
7604 t->fogtexture = NULL;
7605 t->reflectmasktexture = NULL;
7606 t->backgroundbasetexture = NULL;
7607 t->backgroundnmaptexture = r_texture_blanknormalmap;
7608 t->backgroundglosstexture = r_texture_black;
7609 t->backgroundglowtexture = NULL;
7610 t->specularscale = 0;
7611 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7614 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7615 VectorClear(t->dlightcolor);
7616 t->currentnumlayers = 0;
7617 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7619 int blendfunc1, blendfunc2;
7621 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7623 blendfunc1 = GL_SRC_ALPHA;
7624 blendfunc2 = GL_ONE;
7626 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7628 blendfunc1 = GL_SRC_ALPHA;
7629 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7631 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7633 blendfunc1 = t->customblendfunc[0];
7634 blendfunc2 = t->customblendfunc[1];
7638 blendfunc1 = GL_ONE;
7639 blendfunc2 = GL_ZERO;
7641 // don't colormod evilblend textures
7642 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7643 VectorSet(t->lightmapcolor, 1, 1, 1);
7644 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7645 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7647 // fullbright is not affected by r_refdef.lightmapintensity
7648 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]);
7649 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7650 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]);
7651 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7652 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]);
7656 vec3_t ambientcolor;
7658 // set the color tint used for lights affecting this surface
7659 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7661 // q3bsp has no lightmap updates, so the lightstylevalue that
7662 // would normally be baked into the lightmap must be
7663 // applied to the color
7664 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7665 if (model->type == mod_brushq3)
7666 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7667 colorscale *= r_refdef.lightmapintensity;
7668 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7669 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7670 // basic lit geometry
7671 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]);
7672 // add pants/shirt if needed
7673 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7674 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]);
7675 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7676 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]);
7677 // now add ambient passes if needed
7678 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7680 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]);
7681 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7682 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]);
7683 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7684 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]);
7687 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7688 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]);
7689 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7691 // if this is opaque use alpha blend which will darken the earlier
7694 // if this is an alpha blended material, all the earlier passes
7695 // were darkened by fog already, so we only need to add the fog
7696 // color ontop through the fog mask texture
7698 // if this is an additive blended material, all the earlier passes
7699 // were darkened by fog already, and we should not add fog color
7700 // (because the background was not darkened, there is no fog color
7701 // that was lost behind it).
7702 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]);
7706 return t->currentframe;
7709 rsurfacestate_t rsurface;
7711 void RSurf_ActiveWorldEntity(void)
7713 dp_model_t *model = r_refdef.scene.worldmodel;
7714 //if (rsurface.entity == r_refdef.scene.worldentity)
7716 rsurface.entity = r_refdef.scene.worldentity;
7717 rsurface.skeleton = NULL;
7718 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7719 rsurface.ent_skinnum = 0;
7720 rsurface.ent_qwskin = -1;
7721 rsurface.ent_shadertime = 0;
7722 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7723 rsurface.matrix = identitymatrix;
7724 rsurface.inversematrix = identitymatrix;
7725 rsurface.matrixscale = 1;
7726 rsurface.inversematrixscale = 1;
7727 R_EntityMatrix(&identitymatrix);
7728 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7729 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7730 rsurface.fograngerecip = r_refdef.fograngerecip;
7731 rsurface.fogheightfade = r_refdef.fogheightfade;
7732 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7733 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7734 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7735 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7736 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7737 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7738 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7739 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7740 rsurface.colormod[3] = 1;
7741 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);
7742 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7743 rsurface.frameblend[0].lerp = 1;
7744 rsurface.ent_alttextures = false;
7745 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7746 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7747 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7748 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7749 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7750 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7751 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7752 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7753 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7754 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7755 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7756 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7757 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7758 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7759 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7760 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7761 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7762 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7763 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7764 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7765 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7766 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7767 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7768 rsurface.modelelement3i = model->surfmesh.data_element3i;
7769 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7770 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7771 rsurface.modelelement3s = model->surfmesh.data_element3s;
7772 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7773 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7774 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7775 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7776 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7777 rsurface.modelsurfaces = model->data_surfaces;
7778 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7779 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7780 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7781 rsurface.modelgeneratedvertex = false;
7782 rsurface.batchgeneratedvertex = false;
7783 rsurface.batchfirstvertex = 0;
7784 rsurface.batchnumvertices = 0;
7785 rsurface.batchfirsttriangle = 0;
7786 rsurface.batchnumtriangles = 0;
7787 rsurface.batchvertex3f = NULL;
7788 rsurface.batchvertex3f_vertexbuffer = NULL;
7789 rsurface.batchvertex3f_bufferoffset = 0;
7790 rsurface.batchsvector3f = NULL;
7791 rsurface.batchsvector3f_vertexbuffer = NULL;
7792 rsurface.batchsvector3f_bufferoffset = 0;
7793 rsurface.batchtvector3f = NULL;
7794 rsurface.batchtvector3f_vertexbuffer = NULL;
7795 rsurface.batchtvector3f_bufferoffset = 0;
7796 rsurface.batchnormal3f = NULL;
7797 rsurface.batchnormal3f_vertexbuffer = NULL;
7798 rsurface.batchnormal3f_bufferoffset = 0;
7799 rsurface.batchlightmapcolor4f = NULL;
7800 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7801 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7802 rsurface.batchtexcoordtexture2f = NULL;
7803 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7804 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7805 rsurface.batchtexcoordlightmap2f = NULL;
7806 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7807 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7808 rsurface.batchvertexmesh = NULL;
7809 rsurface.batchvertexmeshbuffer = NULL;
7810 rsurface.batchvertex3fbuffer = NULL;
7811 rsurface.batchelement3i = NULL;
7812 rsurface.batchelement3i_indexbuffer = NULL;
7813 rsurface.batchelement3i_bufferoffset = 0;
7814 rsurface.batchelement3s = NULL;
7815 rsurface.batchelement3s_indexbuffer = NULL;
7816 rsurface.batchelement3s_bufferoffset = 0;
7817 rsurface.passcolor4f = NULL;
7818 rsurface.passcolor4f_vertexbuffer = NULL;
7819 rsurface.passcolor4f_bufferoffset = 0;
7822 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7824 dp_model_t *model = ent->model;
7825 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7827 rsurface.entity = (entity_render_t *)ent;
7828 rsurface.skeleton = ent->skeleton;
7829 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7830 rsurface.ent_skinnum = ent->skinnum;
7831 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;
7832 rsurface.ent_shadertime = ent->shadertime;
7833 rsurface.ent_flags = ent->flags;
7834 rsurface.matrix = ent->matrix;
7835 rsurface.inversematrix = ent->inversematrix;
7836 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7837 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7838 R_EntityMatrix(&rsurface.matrix);
7839 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7840 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7841 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7842 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7843 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7844 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7845 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7846 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7847 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7848 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7849 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7850 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7851 rsurface.colormod[3] = ent->alpha;
7852 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7853 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7854 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7855 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7856 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7857 if (ent->model->brush.submodel && !prepass)
7859 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7860 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7862 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7864 if (ent->animcache_vertex3f)
7866 rsurface.modelvertex3f = ent->animcache_vertex3f;
7867 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7868 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7869 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7870 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7871 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7872 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7874 else if (wanttangents)
7876 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7877 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7879 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7880 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7881 rsurface.modelvertexmesh = NULL;
7882 rsurface.modelvertexmeshbuffer = NULL;
7883 rsurface.modelvertex3fbuffer = NULL;
7885 else if (wantnormals)
7887 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7888 rsurface.modelsvector3f = NULL;
7889 rsurface.modeltvector3f = NULL;
7890 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7891 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7892 rsurface.modelvertexmesh = NULL;
7893 rsurface.modelvertexmeshbuffer = NULL;
7894 rsurface.modelvertex3fbuffer = NULL;
7898 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7899 rsurface.modelsvector3f = NULL;
7900 rsurface.modeltvector3f = NULL;
7901 rsurface.modelnormal3f = NULL;
7902 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7903 rsurface.modelvertexmesh = NULL;
7904 rsurface.modelvertexmeshbuffer = NULL;
7905 rsurface.modelvertex3fbuffer = NULL;
7907 rsurface.modelvertex3f_vertexbuffer = 0;
7908 rsurface.modelvertex3f_bufferoffset = 0;
7909 rsurface.modelsvector3f_vertexbuffer = 0;
7910 rsurface.modelsvector3f_bufferoffset = 0;
7911 rsurface.modeltvector3f_vertexbuffer = 0;
7912 rsurface.modeltvector3f_bufferoffset = 0;
7913 rsurface.modelnormal3f_vertexbuffer = 0;
7914 rsurface.modelnormal3f_bufferoffset = 0;
7915 rsurface.modelgeneratedvertex = true;
7919 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7920 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7921 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7922 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7923 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7924 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7925 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7926 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7927 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7928 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7929 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7930 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7931 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7932 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7933 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7934 rsurface.modelgeneratedvertex = false;
7936 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7937 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7938 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7939 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7940 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7941 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7942 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7943 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7944 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7945 rsurface.modelelement3i = model->surfmesh.data_element3i;
7946 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7947 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7948 rsurface.modelelement3s = model->surfmesh.data_element3s;
7949 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7950 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7951 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7952 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7953 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7954 rsurface.modelsurfaces = model->data_surfaces;
7955 rsurface.batchgeneratedvertex = false;
7956 rsurface.batchfirstvertex = 0;
7957 rsurface.batchnumvertices = 0;
7958 rsurface.batchfirsttriangle = 0;
7959 rsurface.batchnumtriangles = 0;
7960 rsurface.batchvertex3f = NULL;
7961 rsurface.batchvertex3f_vertexbuffer = NULL;
7962 rsurface.batchvertex3f_bufferoffset = 0;
7963 rsurface.batchsvector3f = NULL;
7964 rsurface.batchsvector3f_vertexbuffer = NULL;
7965 rsurface.batchsvector3f_bufferoffset = 0;
7966 rsurface.batchtvector3f = NULL;
7967 rsurface.batchtvector3f_vertexbuffer = NULL;
7968 rsurface.batchtvector3f_bufferoffset = 0;
7969 rsurface.batchnormal3f = NULL;
7970 rsurface.batchnormal3f_vertexbuffer = NULL;
7971 rsurface.batchnormal3f_bufferoffset = 0;
7972 rsurface.batchlightmapcolor4f = NULL;
7973 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7974 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7975 rsurface.batchtexcoordtexture2f = NULL;
7976 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7977 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7978 rsurface.batchtexcoordlightmap2f = NULL;
7979 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7980 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7981 rsurface.batchvertexmesh = NULL;
7982 rsurface.batchvertexmeshbuffer = NULL;
7983 rsurface.batchvertex3fbuffer = NULL;
7984 rsurface.batchelement3i = NULL;
7985 rsurface.batchelement3i_indexbuffer = NULL;
7986 rsurface.batchelement3i_bufferoffset = 0;
7987 rsurface.batchelement3s = NULL;
7988 rsurface.batchelement3s_indexbuffer = NULL;
7989 rsurface.batchelement3s_bufferoffset = 0;
7990 rsurface.passcolor4f = NULL;
7991 rsurface.passcolor4f_vertexbuffer = NULL;
7992 rsurface.passcolor4f_bufferoffset = 0;
7995 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)
7997 rsurface.entity = r_refdef.scene.worldentity;
7998 rsurface.skeleton = NULL;
7999 rsurface.ent_skinnum = 0;
8000 rsurface.ent_qwskin = -1;
8001 rsurface.ent_shadertime = shadertime;
8002 rsurface.ent_flags = entflags;
8003 rsurface.modelnumvertices = numvertices;
8004 rsurface.modelnumtriangles = numtriangles;
8005 rsurface.matrix = *matrix;
8006 rsurface.inversematrix = *inversematrix;
8007 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8008 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8009 R_EntityMatrix(&rsurface.matrix);
8010 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8011 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8012 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8013 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8014 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8015 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8016 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8017 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8018 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8019 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8020 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8021 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8022 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);
8023 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8024 rsurface.frameblend[0].lerp = 1;
8025 rsurface.ent_alttextures = false;
8026 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8027 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8030 rsurface.modelvertex3f = (float *)vertex3f;
8031 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8032 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8033 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8035 else if (wantnormals)
8037 rsurface.modelvertex3f = (float *)vertex3f;
8038 rsurface.modelsvector3f = NULL;
8039 rsurface.modeltvector3f = NULL;
8040 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8044 rsurface.modelvertex3f = (float *)vertex3f;
8045 rsurface.modelsvector3f = NULL;
8046 rsurface.modeltvector3f = NULL;
8047 rsurface.modelnormal3f = NULL;
8049 rsurface.modelvertexmesh = NULL;
8050 rsurface.modelvertexmeshbuffer = NULL;
8051 rsurface.modelvertex3fbuffer = NULL;
8052 rsurface.modelvertex3f_vertexbuffer = 0;
8053 rsurface.modelvertex3f_bufferoffset = 0;
8054 rsurface.modelsvector3f_vertexbuffer = 0;
8055 rsurface.modelsvector3f_bufferoffset = 0;
8056 rsurface.modeltvector3f_vertexbuffer = 0;
8057 rsurface.modeltvector3f_bufferoffset = 0;
8058 rsurface.modelnormal3f_vertexbuffer = 0;
8059 rsurface.modelnormal3f_bufferoffset = 0;
8060 rsurface.modelgeneratedvertex = true;
8061 rsurface.modellightmapcolor4f = (float *)color4f;
8062 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8063 rsurface.modellightmapcolor4f_bufferoffset = 0;
8064 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8065 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8066 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8067 rsurface.modeltexcoordlightmap2f = NULL;
8068 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8069 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8070 rsurface.modelelement3i = (int *)element3i;
8071 rsurface.modelelement3i_indexbuffer = NULL;
8072 rsurface.modelelement3i_bufferoffset = 0;
8073 rsurface.modelelement3s = (unsigned short *)element3s;
8074 rsurface.modelelement3s_indexbuffer = NULL;
8075 rsurface.modelelement3s_bufferoffset = 0;
8076 rsurface.modellightmapoffsets = NULL;
8077 rsurface.modelsurfaces = NULL;
8078 rsurface.batchgeneratedvertex = false;
8079 rsurface.batchfirstvertex = 0;
8080 rsurface.batchnumvertices = 0;
8081 rsurface.batchfirsttriangle = 0;
8082 rsurface.batchnumtriangles = 0;
8083 rsurface.batchvertex3f = NULL;
8084 rsurface.batchvertex3f_vertexbuffer = NULL;
8085 rsurface.batchvertex3f_bufferoffset = 0;
8086 rsurface.batchsvector3f = NULL;
8087 rsurface.batchsvector3f_vertexbuffer = NULL;
8088 rsurface.batchsvector3f_bufferoffset = 0;
8089 rsurface.batchtvector3f = NULL;
8090 rsurface.batchtvector3f_vertexbuffer = NULL;
8091 rsurface.batchtvector3f_bufferoffset = 0;
8092 rsurface.batchnormal3f = NULL;
8093 rsurface.batchnormal3f_vertexbuffer = NULL;
8094 rsurface.batchnormal3f_bufferoffset = 0;
8095 rsurface.batchlightmapcolor4f = NULL;
8096 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8097 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8098 rsurface.batchtexcoordtexture2f = NULL;
8099 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8100 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8101 rsurface.batchtexcoordlightmap2f = NULL;
8102 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8103 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8104 rsurface.batchvertexmesh = NULL;
8105 rsurface.batchvertexmeshbuffer = NULL;
8106 rsurface.batchvertex3fbuffer = NULL;
8107 rsurface.batchelement3i = NULL;
8108 rsurface.batchelement3i_indexbuffer = NULL;
8109 rsurface.batchelement3i_bufferoffset = 0;
8110 rsurface.batchelement3s = NULL;
8111 rsurface.batchelement3s_indexbuffer = NULL;
8112 rsurface.batchelement3s_bufferoffset = 0;
8113 rsurface.passcolor4f = NULL;
8114 rsurface.passcolor4f_vertexbuffer = NULL;
8115 rsurface.passcolor4f_bufferoffset = 0;
8117 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8119 if ((wantnormals || wanttangents) && !normal3f)
8121 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8122 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8124 if (wanttangents && !svector3f)
8126 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8127 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8128 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8133 float RSurf_FogPoint(const float *v)
8135 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8136 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8137 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8138 float FogHeightFade = r_refdef.fogheightfade;
8140 unsigned int fogmasktableindex;
8141 if (r_refdef.fogplaneviewabove)
8142 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8144 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8145 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8146 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8149 float RSurf_FogVertex(const float *v)
8151 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8152 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8153 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8154 float FogHeightFade = rsurface.fogheightfade;
8156 unsigned int fogmasktableindex;
8157 if (r_refdef.fogplaneviewabove)
8158 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8160 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8161 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8162 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8165 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8168 for (i = 0;i < numelements;i++)
8169 outelement3i[i] = inelement3i[i] + adjust;
8172 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8173 extern cvar_t gl_vbo;
8174 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8182 int surfacefirsttriangle;
8183 int surfacenumtriangles;
8184 int surfacefirstvertex;
8185 int surfaceendvertex;
8186 int surfacenumvertices;
8187 int batchnumvertices;
8188 int batchnumtriangles;
8192 qboolean dynamicvertex;
8196 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8198 q3shaderinfo_deform_t *deform;
8199 const msurface_t *surface, *firstsurface;
8200 r_vertexmesh_t *vertexmesh;
8201 if (!texturenumsurfaces)
8203 // find vertex range of this surface batch
8205 firstsurface = texturesurfacelist[0];
8206 firsttriangle = firstsurface->num_firsttriangle;
8207 batchnumvertices = 0;
8208 batchnumtriangles = 0;
8209 firstvertex = endvertex = firstsurface->num_firstvertex;
8210 for (i = 0;i < texturenumsurfaces;i++)
8212 surface = texturesurfacelist[i];
8213 if (surface != firstsurface + i)
8215 surfacefirstvertex = surface->num_firstvertex;
8216 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8217 surfacenumvertices = surface->num_vertices;
8218 surfacenumtriangles = surface->num_triangles;
8219 if (firstvertex > surfacefirstvertex)
8220 firstvertex = surfacefirstvertex;
8221 if (endvertex < surfaceendvertex)
8222 endvertex = surfaceendvertex;
8223 batchnumvertices += surfacenumvertices;
8224 batchnumtriangles += surfacenumtriangles;
8227 // we now know the vertex range used, and if there are any gaps in it
8228 rsurface.batchfirstvertex = firstvertex;
8229 rsurface.batchnumvertices = endvertex - firstvertex;
8230 rsurface.batchfirsttriangle = firsttriangle;
8231 rsurface.batchnumtriangles = batchnumtriangles;
8233 // this variable holds flags for which properties have been updated that
8234 // may require regenerating vertexmesh array...
8237 // check if any dynamic vertex processing must occur
8238 dynamicvertex = false;
8240 // if there is a chance of animated vertex colors, it's a dynamic batch
8241 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8243 dynamicvertex = true;
8244 batchneed |= BATCHNEED_NOGAPS;
8245 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8248 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8250 switch (deform->deform)
8253 case Q3DEFORM_PROJECTIONSHADOW:
8254 case Q3DEFORM_TEXT0:
8255 case Q3DEFORM_TEXT1:
8256 case Q3DEFORM_TEXT2:
8257 case Q3DEFORM_TEXT3:
8258 case Q3DEFORM_TEXT4:
8259 case Q3DEFORM_TEXT5:
8260 case Q3DEFORM_TEXT6:
8261 case Q3DEFORM_TEXT7:
8264 case Q3DEFORM_AUTOSPRITE:
8265 dynamicvertex = true;
8266 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8267 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8269 case Q3DEFORM_AUTOSPRITE2:
8270 dynamicvertex = true;
8271 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8272 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8274 case Q3DEFORM_NORMAL:
8275 dynamicvertex = true;
8276 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8277 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8280 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8281 break; // if wavefunc is a nop, ignore this transform
8282 dynamicvertex = true;
8283 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8284 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8286 case Q3DEFORM_BULGE:
8287 dynamicvertex = true;
8288 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8289 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8292 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8293 break; // if wavefunc is a nop, ignore this transform
8294 dynamicvertex = true;
8295 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8296 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8300 switch(rsurface.texture->tcgen.tcgen)
8303 case Q3TCGEN_TEXTURE:
8305 case Q3TCGEN_LIGHTMAP:
8306 dynamicvertex = true;
8307 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8308 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8310 case Q3TCGEN_VECTOR:
8311 dynamicvertex = true;
8312 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8313 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8315 case Q3TCGEN_ENVIRONMENT:
8316 dynamicvertex = true;
8317 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8318 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8321 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8323 dynamicvertex = true;
8324 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8325 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8328 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8330 dynamicvertex = true;
8331 batchneed |= BATCHNEED_NOGAPS;
8332 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8335 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8337 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8338 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8339 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8340 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8341 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8342 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8343 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8346 // when the model data has no vertex buffer (dynamic mesh), we need to
8348 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8349 batchneed |= BATCHNEED_NOGAPS;
8351 // if needsupdate, we have to do a dynamic vertex batch for sure
8352 if (needsupdate & batchneed)
8353 dynamicvertex = true;
8355 // see if we need to build vertexmesh from arrays
8356 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8357 dynamicvertex = true;
8359 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8360 // also some drivers strongly dislike firstvertex
8361 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8362 dynamicvertex = true;
8364 rsurface.batchvertex3f = rsurface.modelvertex3f;
8365 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8366 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8367 rsurface.batchsvector3f = rsurface.modelsvector3f;
8368 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8369 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8370 rsurface.batchtvector3f = rsurface.modeltvector3f;
8371 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8372 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8373 rsurface.batchnormal3f = rsurface.modelnormal3f;
8374 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8375 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8376 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8377 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8378 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8379 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8380 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8381 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8382 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8383 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8384 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8385 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8386 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8387 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8388 rsurface.batchelement3i = rsurface.modelelement3i;
8389 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8390 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8391 rsurface.batchelement3s = rsurface.modelelement3s;
8392 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8393 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8395 // if any dynamic vertex processing has to occur in software, we copy the
8396 // entire surface list together before processing to rebase the vertices
8397 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8399 // if any gaps exist and we do not have a static vertex buffer, we have to
8400 // copy the surface list together to avoid wasting upload bandwidth on the
8401 // vertices in the gaps.
8403 // if gaps exist and we have a static vertex buffer, we still have to
8404 // combine the index buffer ranges into one dynamic index buffer.
8406 // in all cases we end up with data that can be drawn in one call.
8410 // static vertex data, just set pointers...
8411 rsurface.batchgeneratedvertex = false;
8412 // if there are gaps, we want to build a combined index buffer,
8413 // otherwise use the original static buffer with an appropriate offset
8416 // build a new triangle elements array for this batch
8417 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8418 rsurface.batchfirsttriangle = 0;
8420 for (i = 0;i < texturenumsurfaces;i++)
8422 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8423 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8424 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8425 numtriangles += surfacenumtriangles;
8427 rsurface.batchelement3i_indexbuffer = NULL;
8428 rsurface.batchelement3i_bufferoffset = 0;
8429 rsurface.batchelement3s = NULL;
8430 rsurface.batchelement3s_indexbuffer = NULL;
8431 rsurface.batchelement3s_bufferoffset = 0;
8432 if (endvertex <= 65536)
8434 // make a 16bit (unsigned short) index array if possible
8435 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8436 for (i = 0;i < numtriangles*3;i++)
8437 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8443 // something needs software processing, do it for real...
8444 // we only directly handle separate array data in this case and then
8445 // generate interleaved data if needed...
8446 rsurface.batchgeneratedvertex = true;
8448 // now copy the vertex data into a combined array and make an index array
8449 // (this is what Quake3 does all the time)
8450 //if (gaps || rsurface.batchfirstvertex)
8452 rsurface.batchvertex3fbuffer = NULL;
8453 rsurface.batchvertexmesh = NULL;
8454 rsurface.batchvertexmeshbuffer = NULL;
8455 rsurface.batchvertex3f = NULL;
8456 rsurface.batchvertex3f_vertexbuffer = NULL;
8457 rsurface.batchvertex3f_bufferoffset = 0;
8458 rsurface.batchsvector3f = NULL;
8459 rsurface.batchsvector3f_vertexbuffer = NULL;
8460 rsurface.batchsvector3f_bufferoffset = 0;
8461 rsurface.batchtvector3f = NULL;
8462 rsurface.batchtvector3f_vertexbuffer = NULL;
8463 rsurface.batchtvector3f_bufferoffset = 0;
8464 rsurface.batchnormal3f = NULL;
8465 rsurface.batchnormal3f_vertexbuffer = NULL;
8466 rsurface.batchnormal3f_bufferoffset = 0;
8467 rsurface.batchlightmapcolor4f = NULL;
8468 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8469 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8470 rsurface.batchtexcoordtexture2f = NULL;
8471 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8472 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8473 rsurface.batchtexcoordlightmap2f = NULL;
8474 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8475 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8476 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8477 rsurface.batchelement3i_indexbuffer = NULL;
8478 rsurface.batchelement3i_bufferoffset = 0;
8479 rsurface.batchelement3s = NULL;
8480 rsurface.batchelement3s_indexbuffer = NULL;
8481 rsurface.batchelement3s_bufferoffset = 0;
8482 // we'll only be setting up certain arrays as needed
8483 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8484 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8485 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8486 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8487 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8488 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8489 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8491 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8492 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8494 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8495 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8496 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8497 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8498 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8499 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8502 for (i = 0;i < texturenumsurfaces;i++)
8504 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8505 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8506 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8507 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8508 // copy only the data requested
8509 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8510 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8511 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8513 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8514 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8515 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8516 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8517 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8519 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8520 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8522 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8523 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8524 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8525 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8526 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8527 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8529 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8530 numvertices += surfacenumvertices;
8531 numtriangles += surfacenumtriangles;
8534 // generate a 16bit index array as well if possible
8535 // (in general, dynamic batches fit)
8536 if (numvertices <= 65536)
8538 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8539 for (i = 0;i < numtriangles*3;i++)
8540 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8543 // since we've copied everything, the batch now starts at 0
8544 rsurface.batchfirstvertex = 0;
8545 rsurface.batchnumvertices = batchnumvertices;
8546 rsurface.batchfirsttriangle = 0;
8547 rsurface.batchnumtriangles = batchnumtriangles;
8550 // q1bsp surfaces rendered in vertex color mode have to have colors
8551 // calculated based on lightstyles
8552 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8554 // generate color arrays for the surfaces in this list
8559 const unsigned char *lm;
8560 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8561 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8562 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8564 for (i = 0;i < texturenumsurfaces;i++)
8566 surface = texturesurfacelist[i];
8567 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8568 surfacenumvertices = surface->num_vertices;
8569 if (surface->lightmapinfo->samples)
8571 for (j = 0;j < surfacenumvertices;j++)
8573 lm = surface->lightmapinfo->samples + offsets[j];
8574 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8575 VectorScale(lm, scale, c);
8576 if (surface->lightmapinfo->styles[1] != 255)
8578 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8580 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8581 VectorMA(c, scale, lm, c);
8582 if (surface->lightmapinfo->styles[2] != 255)
8585 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8586 VectorMA(c, scale, lm, c);
8587 if (surface->lightmapinfo->styles[3] != 255)
8590 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8591 VectorMA(c, scale, lm, c);
8598 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);
8604 for (j = 0;j < surfacenumvertices;j++)
8606 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8613 // if vertices are deformed (sprite flares and things in maps, possibly
8614 // water waves, bulges and other deformations), modify the copied vertices
8616 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8618 switch (deform->deform)
8621 case Q3DEFORM_PROJECTIONSHADOW:
8622 case Q3DEFORM_TEXT0:
8623 case Q3DEFORM_TEXT1:
8624 case Q3DEFORM_TEXT2:
8625 case Q3DEFORM_TEXT3:
8626 case Q3DEFORM_TEXT4:
8627 case Q3DEFORM_TEXT5:
8628 case Q3DEFORM_TEXT6:
8629 case Q3DEFORM_TEXT7:
8632 case Q3DEFORM_AUTOSPRITE:
8633 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8634 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8635 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8636 VectorNormalize(newforward);
8637 VectorNormalize(newright);
8638 VectorNormalize(newup);
8639 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8640 // rsurface.batchvertex3f_vertexbuffer = NULL;
8641 // rsurface.batchvertex3f_bufferoffset = 0;
8642 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8643 // rsurface.batchsvector3f_vertexbuffer = NULL;
8644 // rsurface.batchsvector3f_bufferoffset = 0;
8645 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8646 // rsurface.batchtvector3f_vertexbuffer = NULL;
8647 // rsurface.batchtvector3f_bufferoffset = 0;
8648 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8649 // rsurface.batchnormal3f_vertexbuffer = NULL;
8650 // rsurface.batchnormal3f_bufferoffset = 0;
8651 // a single autosprite surface can contain multiple sprites...
8652 for (j = 0;j < batchnumvertices - 3;j += 4)
8654 VectorClear(center);
8655 for (i = 0;i < 4;i++)
8656 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8657 VectorScale(center, 0.25f, center);
8658 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8659 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8660 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8661 for (i = 0;i < 4;i++)
8663 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8664 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8667 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8668 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8669 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8671 case Q3DEFORM_AUTOSPRITE2:
8672 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8673 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8674 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8675 VectorNormalize(newforward);
8676 VectorNormalize(newright);
8677 VectorNormalize(newup);
8678 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8679 // rsurface.batchvertex3f_vertexbuffer = NULL;
8680 // rsurface.batchvertex3f_bufferoffset = 0;
8682 const float *v1, *v2;
8692 memset(shortest, 0, sizeof(shortest));
8693 // a single autosprite surface can contain multiple sprites...
8694 for (j = 0;j < batchnumvertices - 3;j += 4)
8696 VectorClear(center);
8697 for (i = 0;i < 4;i++)
8698 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8699 VectorScale(center, 0.25f, center);
8700 // find the two shortest edges, then use them to define the
8701 // axis vectors for rotating around the central axis
8702 for (i = 0;i < 6;i++)
8704 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8705 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8706 l = VectorDistance2(v1, v2);
8707 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8709 l += (1.0f / 1024.0f);
8710 if (shortest[0].length2 > l || i == 0)
8712 shortest[1] = shortest[0];
8713 shortest[0].length2 = l;
8714 shortest[0].v1 = v1;
8715 shortest[0].v2 = v2;
8717 else if (shortest[1].length2 > l || i == 1)
8719 shortest[1].length2 = l;
8720 shortest[1].v1 = v1;
8721 shortest[1].v2 = v2;
8724 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8725 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8726 // this calculates the right vector from the shortest edge
8727 // and the up vector from the edge midpoints
8728 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8729 VectorNormalize(right);
8730 VectorSubtract(end, start, up);
8731 VectorNormalize(up);
8732 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8733 VectorSubtract(rsurface.localvieworigin, center, forward);
8734 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8735 VectorNegate(forward, forward);
8736 VectorReflect(forward, 0, up, forward);
8737 VectorNormalize(forward);
8738 CrossProduct(up, forward, newright);
8739 VectorNormalize(newright);
8740 // rotate the quad around the up axis vector, this is made
8741 // especially easy by the fact we know the quad is flat,
8742 // so we only have to subtract the center position and
8743 // measure distance along the right vector, and then
8744 // multiply that by the newright vector and add back the
8746 // we also need to subtract the old position to undo the
8747 // displacement from the center, which we do with a
8748 // DotProduct, the subtraction/addition of center is also
8749 // optimized into DotProducts here
8750 l = DotProduct(right, center);
8751 for (i = 0;i < 4;i++)
8753 v1 = rsurface.batchvertex3f + 3*(j+i);
8754 f = DotProduct(right, v1) - l;
8755 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8759 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8761 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8762 // rsurface.batchnormal3f_vertexbuffer = NULL;
8763 // rsurface.batchnormal3f_bufferoffset = 0;
8764 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8766 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8768 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8769 // rsurface.batchsvector3f_vertexbuffer = NULL;
8770 // rsurface.batchsvector3f_bufferoffset = 0;
8771 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8772 // rsurface.batchtvector3f_vertexbuffer = NULL;
8773 // rsurface.batchtvector3f_bufferoffset = 0;
8774 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);
8777 case Q3DEFORM_NORMAL:
8778 // deform the normals to make reflections wavey
8779 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8780 rsurface.batchnormal3f_vertexbuffer = NULL;
8781 rsurface.batchnormal3f_bufferoffset = 0;
8782 for (j = 0;j < batchnumvertices;j++)
8785 float *normal = rsurface.batchnormal3f + 3*j;
8786 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8787 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8788 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]);
8789 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]);
8790 VectorNormalize(normal);
8792 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8794 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8795 // rsurface.batchsvector3f_vertexbuffer = NULL;
8796 // rsurface.batchsvector3f_bufferoffset = 0;
8797 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798 // rsurface.batchtvector3f_vertexbuffer = NULL;
8799 // rsurface.batchtvector3f_bufferoffset = 0;
8800 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);
8804 // deform vertex array to make wavey water and flags and such
8805 waveparms[0] = deform->waveparms[0];
8806 waveparms[1] = deform->waveparms[1];
8807 waveparms[2] = deform->waveparms[2];
8808 waveparms[3] = deform->waveparms[3];
8809 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8810 break; // if wavefunc is a nop, don't make a dynamic vertex array
8811 // this is how a divisor of vertex influence on deformation
8812 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8813 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8814 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8815 // rsurface.batchvertex3f_vertexbuffer = NULL;
8816 // rsurface.batchvertex3f_bufferoffset = 0;
8817 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8818 // rsurface.batchnormal3f_vertexbuffer = NULL;
8819 // rsurface.batchnormal3f_bufferoffset = 0;
8820 for (j = 0;j < batchnumvertices;j++)
8822 // if the wavefunc depends on time, evaluate it per-vertex
8825 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8826 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8828 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8830 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8831 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8832 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8834 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8835 // rsurface.batchsvector3f_vertexbuffer = NULL;
8836 // rsurface.batchsvector3f_bufferoffset = 0;
8837 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8838 // rsurface.batchtvector3f_vertexbuffer = NULL;
8839 // rsurface.batchtvector3f_bufferoffset = 0;
8840 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);
8843 case Q3DEFORM_BULGE:
8844 // deform vertex array to make the surface have moving bulges
8845 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8846 // rsurface.batchvertex3f_vertexbuffer = NULL;
8847 // rsurface.batchvertex3f_bufferoffset = 0;
8848 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8849 // rsurface.batchnormal3f_vertexbuffer = NULL;
8850 // rsurface.batchnormal3f_bufferoffset = 0;
8851 for (j = 0;j < batchnumvertices;j++)
8853 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8854 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8856 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8857 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8858 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8860 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8861 // rsurface.batchsvector3f_vertexbuffer = NULL;
8862 // rsurface.batchsvector3f_bufferoffset = 0;
8863 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8864 // rsurface.batchtvector3f_vertexbuffer = NULL;
8865 // rsurface.batchtvector3f_bufferoffset = 0;
8866 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);
8870 // deform vertex array
8871 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8872 break; // if wavefunc is a nop, don't make a dynamic vertex array
8873 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8874 VectorScale(deform->parms, scale, waveparms);
8875 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8876 // rsurface.batchvertex3f_vertexbuffer = NULL;
8877 // rsurface.batchvertex3f_bufferoffset = 0;
8878 for (j = 0;j < batchnumvertices;j++)
8879 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8884 // generate texcoords based on the chosen texcoord source
8885 switch(rsurface.texture->tcgen.tcgen)
8888 case Q3TCGEN_TEXTURE:
8890 case Q3TCGEN_LIGHTMAP:
8891 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8892 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8893 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8894 if (rsurface.batchtexcoordlightmap2f)
8895 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8897 case Q3TCGEN_VECTOR:
8898 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8899 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8900 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8901 for (j = 0;j < batchnumvertices;j++)
8903 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8904 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8907 case Q3TCGEN_ENVIRONMENT:
8908 // make environment reflections using a spheremap
8909 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8910 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8911 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8912 for (j = 0;j < batchnumvertices;j++)
8914 // identical to Q3A's method, but executed in worldspace so
8915 // carried models can be shiny too
8917 float viewer[3], d, reflected[3], worldreflected[3];
8919 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8920 // VectorNormalize(viewer);
8922 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8924 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8925 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8926 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8927 // note: this is proportinal to viewer, so we can normalize later
8929 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8930 VectorNormalize(worldreflected);
8932 // note: this sphere map only uses world x and z!
8933 // so positive and negative y will LOOK THE SAME.
8934 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8935 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8939 // the only tcmod that needs software vertex processing is turbulent, so
8940 // check for it here and apply the changes if needed
8941 // and we only support that as the first one
8942 // (handling a mixture of turbulent and other tcmods would be problematic
8943 // without punting it entirely to a software path)
8944 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8946 amplitude = rsurface.texture->tcmods[0].parms[1];
8947 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8948 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8949 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8950 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8951 for (j = 0;j < batchnumvertices;j++)
8953 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);
8954 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8958 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8960 // convert the modified arrays to vertex structs
8961 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8962 // rsurface.batchvertexmeshbuffer = NULL;
8963 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8964 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8965 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8966 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8967 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8968 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8969 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8971 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8973 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8974 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8977 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8978 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8979 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8980 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8981 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8982 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8983 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8984 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8985 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8989 void RSurf_DrawBatch(void)
8991 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8992 // through the pipeline, killing it earlier in the pipeline would have
8993 // per-surface overhead rather than per-batch overhead, so it's best to
8994 // reject it here, before it hits glDraw.
8995 if (rsurface.batchnumtriangles == 0)
8998 // batch debugging code
8999 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9005 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9006 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9009 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9011 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9013 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9014 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);
9021 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);
9024 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9026 // pick the closest matching water plane
9027 int planeindex, vertexindex, bestplaneindex = -1;
9031 r_waterstate_waterplane_t *p;
9032 qboolean prepared = false;
9034 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9036 if(p->camera_entity != rsurface.texture->camera_entity)
9041 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9043 if(rsurface.batchnumvertices == 0)
9046 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9048 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9049 d += fabs(PlaneDiff(vert, &p->plane));
9051 if (bestd > d || bestplaneindex < 0)
9054 bestplaneindex = planeindex;
9057 return bestplaneindex;
9058 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9059 // this situation though, as it might be better to render single larger
9060 // batches with useless stuff (backface culled for example) than to
9061 // render multiple smaller batches
9064 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9067 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9068 rsurface.passcolor4f_vertexbuffer = 0;
9069 rsurface.passcolor4f_bufferoffset = 0;
9070 for (i = 0;i < rsurface.batchnumvertices;i++)
9071 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9074 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9081 if (rsurface.passcolor4f)
9083 // generate color arrays
9084 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9085 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9086 rsurface.passcolor4f_vertexbuffer = 0;
9087 rsurface.passcolor4f_bufferoffset = 0;
9088 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)
9090 f = RSurf_FogVertex(v);
9099 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9100 rsurface.passcolor4f_vertexbuffer = 0;
9101 rsurface.passcolor4f_bufferoffset = 0;
9102 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9104 f = RSurf_FogVertex(v);
9113 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9120 if (!rsurface.passcolor4f)
9122 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9123 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9124 rsurface.passcolor4f_vertexbuffer = 0;
9125 rsurface.passcolor4f_bufferoffset = 0;
9126 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)
9128 f = RSurf_FogVertex(v);
9129 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9130 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9131 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9136 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9141 if (!rsurface.passcolor4f)
9143 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9144 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9145 rsurface.passcolor4f_vertexbuffer = 0;
9146 rsurface.passcolor4f_bufferoffset = 0;
9147 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9156 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9161 if (!rsurface.passcolor4f)
9163 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9164 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9165 rsurface.passcolor4f_vertexbuffer = 0;
9166 rsurface.passcolor4f_bufferoffset = 0;
9167 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9169 c2[0] = c[0] + r_refdef.scene.ambient;
9170 c2[1] = c[1] + r_refdef.scene.ambient;
9171 c2[2] = c[2] + r_refdef.scene.ambient;
9176 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9179 rsurface.passcolor4f = NULL;
9180 rsurface.passcolor4f_vertexbuffer = 0;
9181 rsurface.passcolor4f_bufferoffset = 0;
9182 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9183 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9184 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9185 GL_Color(r, g, b, a);
9186 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9190 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9192 // TODO: optimize applyfog && applycolor case
9193 // just apply fog if necessary, and tint the fog color array if necessary
9194 rsurface.passcolor4f = NULL;
9195 rsurface.passcolor4f_vertexbuffer = 0;
9196 rsurface.passcolor4f_bufferoffset = 0;
9197 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9198 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9199 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9200 GL_Color(r, g, b, a);
9204 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9207 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9208 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9209 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9210 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9211 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9212 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9213 GL_Color(r, g, b, a);
9217 static void RSurf_DrawBatch_GL11_ClampColor(void)
9222 if (!rsurface.passcolor4f)
9224 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9226 c2[0] = bound(0.0f, c1[0], 1.0f);
9227 c2[1] = bound(0.0f, c1[1], 1.0f);
9228 c2[2] = bound(0.0f, c1[2], 1.0f);
9229 c2[3] = bound(0.0f, c1[3], 1.0f);
9233 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9243 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9244 rsurface.passcolor4f_vertexbuffer = 0;
9245 rsurface.passcolor4f_bufferoffset = 0;
9246 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)
9248 f = -DotProduct(r_refdef.view.forward, n);
9250 f = f * 0.85 + 0.15; // work around so stuff won't get black
9251 f *= r_refdef.lightmapintensity;
9252 Vector4Set(c, f, f, f, 1);
9256 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9258 RSurf_DrawBatch_GL11_ApplyFakeLight();
9259 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9260 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9261 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9262 GL_Color(r, g, b, a);
9266 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9274 vec3_t ambientcolor;
9275 vec3_t diffusecolor;
9279 VectorCopy(rsurface.modellight_lightdir, lightdir);
9280 f = 0.5f * r_refdef.lightmapintensity;
9281 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9282 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9283 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9284 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9285 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9286 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9288 if (VectorLength2(diffusecolor) > 0)
9290 // q3-style directional shading
9291 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9292 rsurface.passcolor4f_vertexbuffer = 0;
9293 rsurface.passcolor4f_bufferoffset = 0;
9294 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)
9296 if ((f = DotProduct(n, lightdir)) > 0)
9297 VectorMA(ambientcolor, f, diffusecolor, c);
9299 VectorCopy(ambientcolor, c);
9306 *applycolor = false;
9310 *r = ambientcolor[0];
9311 *g = ambientcolor[1];
9312 *b = ambientcolor[2];
9313 rsurface.passcolor4f = NULL;
9314 rsurface.passcolor4f_vertexbuffer = 0;
9315 rsurface.passcolor4f_bufferoffset = 0;
9319 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9321 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9322 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9323 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9324 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9325 GL_Color(r, g, b, a);
9329 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9337 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9338 rsurface.passcolor4f_vertexbuffer = 0;
9339 rsurface.passcolor4f_bufferoffset = 0;
9341 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9343 f = 1 - RSurf_FogVertex(v);
9351 void RSurf_SetupDepthAndCulling(void)
9353 // submodels are biased to avoid z-fighting with world surfaces that they
9354 // may be exactly overlapping (avoids z-fighting artifacts on certain
9355 // doors and things in Quake maps)
9356 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9357 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9358 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9359 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9362 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9364 // transparent sky would be ridiculous
9365 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9367 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9368 skyrenderlater = true;
9369 RSurf_SetupDepthAndCulling();
9371 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9372 // skymasking on them, and Quake3 never did sky masking (unlike
9373 // software Quake and software Quake2), so disable the sky masking
9374 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9375 // and skymasking also looks very bad when noclipping outside the
9376 // level, so don't use it then either.
9377 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9379 R_Mesh_ResetTextureState();
9380 if (skyrendermasked)
9382 R_SetupShader_DepthOrShadow();
9383 // depth-only (masking)
9384 GL_ColorMask(0,0,0,0);
9385 // just to make sure that braindead drivers don't draw
9386 // anything despite that colormask...
9387 GL_BlendFunc(GL_ZERO, GL_ONE);
9388 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9389 if (rsurface.batchvertex3fbuffer)
9390 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9392 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9396 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9398 GL_BlendFunc(GL_ONE, GL_ZERO);
9399 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9400 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9401 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9404 if (skyrendermasked)
9405 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9407 R_Mesh_ResetTextureState();
9408 GL_Color(1, 1, 1, 1);
9411 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9412 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9413 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9415 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9419 // render screenspace normalmap to texture
9421 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9426 // bind lightmap texture
9428 // water/refraction/reflection/camera surfaces have to be handled specially
9429 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9431 int start, end, startplaneindex;
9432 for (start = 0;start < texturenumsurfaces;start = end)
9434 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9435 if(startplaneindex < 0)
9437 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9438 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9442 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9444 // now that we have a batch using the same planeindex, render it
9445 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9447 // render water or distortion background
9449 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));
9451 // blend surface on top
9452 GL_DepthMask(false);
9453 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9456 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9458 // render surface with reflection texture as input
9459 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9460 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));
9467 // render surface batch normally
9468 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9469 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9473 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9475 // OpenGL 1.3 path - anything not completely ancient
9476 qboolean applycolor;
9479 const texturelayer_t *layer;
9480 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);
9481 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9483 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9486 int layertexrgbscale;
9487 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9489 if (layerindex == 0)
9493 GL_AlphaTest(false);
9494 GL_DepthFunc(GL_EQUAL);
9497 GL_DepthMask(layer->depthmask && writedepth);
9498 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9499 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9501 layertexrgbscale = 4;
9502 VectorScale(layer->color, 0.25f, layercolor);
9504 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9506 layertexrgbscale = 2;
9507 VectorScale(layer->color, 0.5f, layercolor);
9511 layertexrgbscale = 1;
9512 VectorScale(layer->color, 1.0f, layercolor);
9514 layercolor[3] = layer->color[3];
9515 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9516 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9517 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9518 switch (layer->type)
9520 case TEXTURELAYERTYPE_LITTEXTURE:
9521 // single-pass lightmapped texture with 2x rgbscale
9522 R_Mesh_TexBind(0, r_texture_white);
9523 R_Mesh_TexMatrix(0, NULL);
9524 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9525 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9526 R_Mesh_TexBind(1, layer->texture);
9527 R_Mesh_TexMatrix(1, &layer->texmatrix);
9528 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9529 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9530 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9531 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9532 else if (FAKELIGHT_ENABLED)
9533 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9534 else if (rsurface.uselightmaptexture)
9535 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9537 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9539 case TEXTURELAYERTYPE_TEXTURE:
9540 // singletexture unlit texture with transparency support
9541 R_Mesh_TexBind(0, layer->texture);
9542 R_Mesh_TexMatrix(0, &layer->texmatrix);
9543 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9544 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9545 R_Mesh_TexBind(1, 0);
9546 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9547 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9549 case TEXTURELAYERTYPE_FOG:
9550 // singletexture fogging
9553 R_Mesh_TexBind(0, layer->texture);
9554 R_Mesh_TexMatrix(0, &layer->texmatrix);
9555 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9556 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9560 R_Mesh_TexBind(0, 0);
9561 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9563 R_Mesh_TexBind(1, 0);
9564 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9565 // generate a color array for the fog pass
9566 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9567 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9571 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9574 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9576 GL_DepthFunc(GL_LEQUAL);
9577 GL_AlphaTest(false);
9581 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9583 // OpenGL 1.1 - crusty old voodoo path
9586 const texturelayer_t *layer;
9587 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);
9588 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9590 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9592 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9594 if (layerindex == 0)
9598 GL_AlphaTest(false);
9599 GL_DepthFunc(GL_EQUAL);
9602 GL_DepthMask(layer->depthmask && writedepth);
9603 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9604 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9605 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9606 switch (layer->type)
9608 case TEXTURELAYERTYPE_LITTEXTURE:
9609 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9611 // two-pass lit texture with 2x rgbscale
9612 // first the lightmap pass
9613 R_Mesh_TexBind(0, r_texture_white);
9614 R_Mesh_TexMatrix(0, NULL);
9615 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9616 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9617 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9618 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9619 else if (FAKELIGHT_ENABLED)
9620 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9621 else if (rsurface.uselightmaptexture)
9622 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9624 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9625 // then apply the texture to it
9626 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9627 R_Mesh_TexBind(0, layer->texture);
9628 R_Mesh_TexMatrix(0, &layer->texmatrix);
9629 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9630 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9631 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);
9635 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9636 R_Mesh_TexBind(0, layer->texture);
9637 R_Mesh_TexMatrix(0, &layer->texmatrix);
9638 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9639 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9640 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9641 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);
9643 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);
9646 case TEXTURELAYERTYPE_TEXTURE:
9647 // singletexture unlit texture with transparency support
9648 R_Mesh_TexBind(0, layer->texture);
9649 R_Mesh_TexMatrix(0, &layer->texmatrix);
9650 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9651 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9652 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);
9654 case TEXTURELAYERTYPE_FOG:
9655 // singletexture fogging
9658 R_Mesh_TexBind(0, layer->texture);
9659 R_Mesh_TexMatrix(0, &layer->texmatrix);
9660 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9661 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9665 R_Mesh_TexBind(0, 0);
9666 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9668 // generate a color array for the fog pass
9669 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9670 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9674 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9677 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9679 GL_DepthFunc(GL_LEQUAL);
9680 GL_AlphaTest(false);
9684 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9688 r_vertexgeneric_t *batchvertex;
9691 // R_Mesh_ResetTextureState();
9692 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9694 if(rsurface.texture && rsurface.texture->currentskinframe)
9696 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9697 c[3] *= rsurface.texture->currentalpha;
9707 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9709 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9710 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9711 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9714 // brighten it up (as texture value 127 means "unlit")
9715 c[0] *= 2 * r_refdef.view.colorscale;
9716 c[1] *= 2 * r_refdef.view.colorscale;
9717 c[2] *= 2 * r_refdef.view.colorscale;
9719 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9720 c[3] *= r_wateralpha.value;
9722 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9724 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9725 GL_DepthMask(false);
9727 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9729 GL_BlendFunc(GL_ONE, GL_ONE);
9730 GL_DepthMask(false);
9732 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9734 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9735 GL_DepthMask(false);
9737 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9739 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9740 GL_DepthMask(false);
9744 GL_BlendFunc(GL_ONE, GL_ZERO);
9745 GL_DepthMask(writedepth);
9748 if (r_showsurfaces.integer == 3)
9750 rsurface.passcolor4f = NULL;
9752 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9754 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9756 rsurface.passcolor4f = NULL;
9757 rsurface.passcolor4f_vertexbuffer = 0;
9758 rsurface.passcolor4f_bufferoffset = 0;
9760 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9762 qboolean applycolor = true;
9765 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9767 r_refdef.lightmapintensity = 1;
9768 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9769 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9771 else if (FAKELIGHT_ENABLED)
9773 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9775 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9776 RSurf_DrawBatch_GL11_ApplyFakeLight();
9777 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9781 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9783 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9784 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9785 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9788 if(!rsurface.passcolor4f)
9789 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9791 RSurf_DrawBatch_GL11_ApplyAmbient();
9792 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9793 if(r_refdef.fogenabled)
9794 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9795 RSurf_DrawBatch_GL11_ClampColor();
9797 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9798 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9801 else if (!r_refdef.view.showdebug)
9803 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9804 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9805 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9807 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9808 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9810 R_Mesh_PrepareVertices_Generic_Unlock();
9813 else if (r_showsurfaces.integer == 4)
9815 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9816 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9817 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9819 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9820 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9821 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9823 R_Mesh_PrepareVertices_Generic_Unlock();
9826 else if (r_showsurfaces.integer == 2)
9829 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9830 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9831 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9833 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9834 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9835 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9836 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9837 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9838 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9839 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9841 R_Mesh_PrepareVertices_Generic_Unlock();
9842 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9846 int texturesurfaceindex;
9848 const msurface_t *surface;
9849 float surfacecolor4f[4];
9850 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9851 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9853 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9855 surface = texturesurfacelist[texturesurfaceindex];
9856 k = (int)(((size_t)surface) / sizeof(msurface_t));
9857 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9858 for (j = 0;j < surface->num_vertices;j++)
9860 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9861 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9865 R_Mesh_PrepareVertices_Generic_Unlock();
9870 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9873 RSurf_SetupDepthAndCulling();
9874 if (r_showsurfaces.integer)
9876 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9879 switch (vid.renderpath)
9881 case RENDERPATH_GL20:
9882 case RENDERPATH_D3D9:
9883 case RENDERPATH_D3D10:
9884 case RENDERPATH_D3D11:
9885 case RENDERPATH_SOFT:
9886 case RENDERPATH_GLES2:
9887 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9889 case RENDERPATH_GL13:
9890 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9892 case RENDERPATH_GL11:
9893 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9899 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9902 RSurf_SetupDepthAndCulling();
9903 if (r_showsurfaces.integer)
9905 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9908 switch (vid.renderpath)
9910 case RENDERPATH_GL20:
9911 case RENDERPATH_D3D9:
9912 case RENDERPATH_D3D10:
9913 case RENDERPATH_D3D11:
9914 case RENDERPATH_SOFT:
9915 case RENDERPATH_GLES2:
9916 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9918 case RENDERPATH_GL13:
9919 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9921 case RENDERPATH_GL11:
9922 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9928 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9931 int texturenumsurfaces, endsurface;
9933 const msurface_t *surface;
9934 #define MAXBATCH_TRANSPARENTSURFACES 256
9935 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9937 // if the model is static it doesn't matter what value we give for
9938 // wantnormals and wanttangents, so this logic uses only rules applicable
9939 // to a model, knowing that they are meaningless otherwise
9940 if (ent == r_refdef.scene.worldentity)
9941 RSurf_ActiveWorldEntity();
9942 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9943 RSurf_ActiveModelEntity(ent, false, false, false);
9946 switch (vid.renderpath)
9948 case RENDERPATH_GL20:
9949 case RENDERPATH_D3D9:
9950 case RENDERPATH_D3D10:
9951 case RENDERPATH_D3D11:
9952 case RENDERPATH_SOFT:
9953 case RENDERPATH_GLES2:
9954 RSurf_ActiveModelEntity(ent, true, true, false);
9956 case RENDERPATH_GL13:
9957 case RENDERPATH_GL11:
9958 RSurf_ActiveModelEntity(ent, true, false, false);
9963 if (r_transparentdepthmasking.integer)
9965 qboolean setup = false;
9966 for (i = 0;i < numsurfaces;i = j)
9969 surface = rsurface.modelsurfaces + surfacelist[i];
9970 texture = surface->texture;
9971 rsurface.texture = R_GetCurrentTexture(texture);
9972 rsurface.lightmaptexture = NULL;
9973 rsurface.deluxemaptexture = NULL;
9974 rsurface.uselightmaptexture = false;
9975 // scan ahead until we find a different texture
9976 endsurface = min(i + 1024, numsurfaces);
9977 texturenumsurfaces = 0;
9978 texturesurfacelist[texturenumsurfaces++] = surface;
9979 for (;j < endsurface;j++)
9981 surface = rsurface.modelsurfaces + surfacelist[j];
9982 if (texture != surface->texture)
9984 texturesurfacelist[texturenumsurfaces++] = surface;
9986 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9988 // render the range of surfaces as depth
9992 GL_ColorMask(0,0,0,0);
9995 GL_BlendFunc(GL_ONE, GL_ZERO);
9997 // R_Mesh_ResetTextureState();
9998 R_SetupShader_DepthOrShadow();
10000 RSurf_SetupDepthAndCulling();
10001 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10002 if (rsurface.batchvertex3fbuffer)
10003 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10005 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10009 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10012 for (i = 0;i < numsurfaces;i = j)
10015 surface = rsurface.modelsurfaces + surfacelist[i];
10016 texture = surface->texture;
10017 rsurface.texture = R_GetCurrentTexture(texture);
10018 // scan ahead until we find a different texture
10019 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10020 texturenumsurfaces = 0;
10021 texturesurfacelist[texturenumsurfaces++] = surface;
10022 if(FAKELIGHT_ENABLED)
10024 rsurface.lightmaptexture = NULL;
10025 rsurface.deluxemaptexture = NULL;
10026 rsurface.uselightmaptexture = false;
10027 for (;j < endsurface;j++)
10029 surface = rsurface.modelsurfaces + surfacelist[j];
10030 if (texture != surface->texture)
10032 texturesurfacelist[texturenumsurfaces++] = surface;
10037 rsurface.lightmaptexture = surface->lightmaptexture;
10038 rsurface.deluxemaptexture = surface->deluxemaptexture;
10039 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10040 for (;j < endsurface;j++)
10042 surface = rsurface.modelsurfaces + surfacelist[j];
10043 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10045 texturesurfacelist[texturenumsurfaces++] = surface;
10048 // render the range of surfaces
10049 if (ent == r_refdef.scene.worldentity)
10050 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10052 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10054 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10057 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10059 // transparent surfaces get pushed off into the transparent queue
10060 int surfacelistindex;
10061 const msurface_t *surface;
10062 vec3_t tempcenter, center;
10063 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10065 surface = texturesurfacelist[surfacelistindex];
10066 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10067 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10068 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10069 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10070 if (queueentity->transparent_offset) // transparent offset
10072 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10073 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10074 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10076 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10080 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10082 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10084 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10086 RSurf_SetupDepthAndCulling();
10087 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10088 if (rsurface.batchvertex3fbuffer)
10089 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10091 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10095 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10097 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10100 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10103 if (!rsurface.texture->currentnumlayers)
10105 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10106 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10108 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10110 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10111 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10112 else if (!rsurface.texture->currentnumlayers)
10114 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10116 // in the deferred case, transparent surfaces were queued during prepass
10117 if (!r_shadow_usingdeferredprepass)
10118 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10122 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10123 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10128 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10131 texture_t *texture;
10132 R_FrameData_SetMark();
10133 // break the surface list down into batches by texture and use of lightmapping
10134 for (i = 0;i < numsurfaces;i = j)
10137 // texture is the base texture pointer, rsurface.texture is the
10138 // current frame/skin the texture is directing us to use (for example
10139 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10140 // use skin 1 instead)
10141 texture = surfacelist[i]->texture;
10142 rsurface.texture = R_GetCurrentTexture(texture);
10143 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10145 // if this texture is not the kind we want, skip ahead to the next one
10146 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10150 if(FAKELIGHT_ENABLED || depthonly || prepass)
10152 rsurface.lightmaptexture = NULL;
10153 rsurface.deluxemaptexture = NULL;
10154 rsurface.uselightmaptexture = false;
10155 // simply scan ahead until we find a different texture or lightmap state
10156 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10161 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10162 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10163 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10164 // simply scan ahead until we find a different texture or lightmap state
10165 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10168 // render the range of surfaces
10169 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10171 R_FrameData_ReturnToMark();
10174 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10178 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10181 if (!rsurface.texture->currentnumlayers)
10183 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10184 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10186 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10188 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10189 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10190 else if (!rsurface.texture->currentnumlayers)
10192 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10194 // in the deferred case, transparent surfaces were queued during prepass
10195 if (!r_shadow_usingdeferredprepass)
10196 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10200 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10201 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10206 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10209 texture_t *texture;
10210 R_FrameData_SetMark();
10211 // break the surface list down into batches by texture and use of lightmapping
10212 for (i = 0;i < numsurfaces;i = j)
10215 // texture is the base texture pointer, rsurface.texture is the
10216 // current frame/skin the texture is directing us to use (for example
10217 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10218 // use skin 1 instead)
10219 texture = surfacelist[i]->texture;
10220 rsurface.texture = R_GetCurrentTexture(texture);
10221 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10223 // if this texture is not the kind we want, skip ahead to the next one
10224 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10228 if(FAKELIGHT_ENABLED || depthonly || prepass)
10230 rsurface.lightmaptexture = NULL;
10231 rsurface.deluxemaptexture = NULL;
10232 rsurface.uselightmaptexture = false;
10233 // simply scan ahead until we find a different texture or lightmap state
10234 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10239 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10240 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10241 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10242 // simply scan ahead until we find a different texture or lightmap state
10243 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10246 // render the range of surfaces
10247 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10249 R_FrameData_ReturnToMark();
10252 float locboxvertex3f[6*4*3] =
10254 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10255 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10256 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10257 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10258 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10259 1,0,0, 0,0,0, 0,1,0, 1,1,0
10262 unsigned short locboxelements[6*2*3] =
10267 12,13,14, 12,14,15,
10268 16,17,18, 16,18,19,
10272 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10275 cl_locnode_t *loc = (cl_locnode_t *)ent;
10277 float vertex3f[6*4*3];
10279 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10280 GL_DepthMask(false);
10281 GL_DepthRange(0, 1);
10282 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10283 GL_DepthTest(true);
10284 GL_CullFace(GL_NONE);
10285 R_EntityMatrix(&identitymatrix);
10287 // R_Mesh_ResetTextureState();
10289 i = surfacelist[0];
10290 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10291 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10292 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10293 surfacelist[0] < 0 ? 0.5f : 0.125f);
10295 if (VectorCompare(loc->mins, loc->maxs))
10297 VectorSet(size, 2, 2, 2);
10298 VectorMA(loc->mins, -0.5f, size, mins);
10302 VectorCopy(loc->mins, mins);
10303 VectorSubtract(loc->maxs, loc->mins, size);
10306 for (i = 0;i < 6*4*3;)
10307 for (j = 0;j < 3;j++, i++)
10308 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10310 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10311 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10312 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10315 void R_DrawLocs(void)
10318 cl_locnode_t *loc, *nearestloc;
10320 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10321 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10323 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10324 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10328 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10330 if (decalsystem->decals)
10331 Mem_Free(decalsystem->decals);
10332 memset(decalsystem, 0, sizeof(*decalsystem));
10335 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)
10338 tridecal_t *decals;
10341 // expand or initialize the system
10342 if (decalsystem->maxdecals <= decalsystem->numdecals)
10344 decalsystem_t old = *decalsystem;
10345 qboolean useshortelements;
10346 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10347 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10348 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)));
10349 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10350 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10351 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10352 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10353 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10354 if (decalsystem->numdecals)
10355 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10357 Mem_Free(old.decals);
10358 for (i = 0;i < decalsystem->maxdecals*3;i++)
10359 decalsystem->element3i[i] = i;
10360 if (useshortelements)
10361 for (i = 0;i < decalsystem->maxdecals*3;i++)
10362 decalsystem->element3s[i] = i;
10365 // grab a decal and search for another free slot for the next one
10366 decals = decalsystem->decals;
10367 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10368 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10370 decalsystem->freedecal = i;
10371 if (decalsystem->numdecals <= i)
10372 decalsystem->numdecals = i + 1;
10374 // initialize the decal
10376 decal->triangleindex = triangleindex;
10377 decal->surfaceindex = surfaceindex;
10378 decal->decalsequence = decalsequence;
10379 decal->color4f[0][0] = c0[0];
10380 decal->color4f[0][1] = c0[1];
10381 decal->color4f[0][2] = c0[2];
10382 decal->color4f[0][3] = 1;
10383 decal->color4f[1][0] = c1[0];
10384 decal->color4f[1][1] = c1[1];
10385 decal->color4f[1][2] = c1[2];
10386 decal->color4f[1][3] = 1;
10387 decal->color4f[2][0] = c2[0];
10388 decal->color4f[2][1] = c2[1];
10389 decal->color4f[2][2] = c2[2];
10390 decal->color4f[2][3] = 1;
10391 decal->vertex3f[0][0] = v0[0];
10392 decal->vertex3f[0][1] = v0[1];
10393 decal->vertex3f[0][2] = v0[2];
10394 decal->vertex3f[1][0] = v1[0];
10395 decal->vertex3f[1][1] = v1[1];
10396 decal->vertex3f[1][2] = v1[2];
10397 decal->vertex3f[2][0] = v2[0];
10398 decal->vertex3f[2][1] = v2[1];
10399 decal->vertex3f[2][2] = v2[2];
10400 decal->texcoord2f[0][0] = t0[0];
10401 decal->texcoord2f[0][1] = t0[1];
10402 decal->texcoord2f[1][0] = t1[0];
10403 decal->texcoord2f[1][1] = t1[1];
10404 decal->texcoord2f[2][0] = t2[0];
10405 decal->texcoord2f[2][1] = t2[1];
10406 TriangleNormal(v0, v1, v2, decal->plane);
10407 VectorNormalize(decal->plane);
10408 decal->plane[3] = DotProduct(v0, decal->plane);
10411 extern cvar_t cl_decals_bias;
10412 extern cvar_t cl_decals_models;
10413 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10414 // baseparms, parms, temps
10415 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)
10420 const float *vertex3f;
10421 const float *normal3f;
10423 float points[2][9][3];
10430 e = rsurface.modelelement3i + 3*triangleindex;
10432 vertex3f = rsurface.modelvertex3f;
10433 normal3f = rsurface.modelnormal3f;
10437 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10439 index = 3*e[cornerindex];
10440 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10445 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10447 index = 3*e[cornerindex];
10448 VectorCopy(vertex3f + index, v[cornerindex]);
10453 //TriangleNormal(v[0], v[1], v[2], normal);
10454 //if (DotProduct(normal, localnormal) < 0.0f)
10456 // clip by each of the box planes formed from the projection matrix
10457 // if anything survives, we emit the decal
10458 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]);
10461 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]);
10464 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]);
10467 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]);
10470 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]);
10473 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]);
10476 // some part of the triangle survived, so we have to accept it...
10479 // dynamic always uses the original triangle
10481 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10483 index = 3*e[cornerindex];
10484 VectorCopy(vertex3f + index, v[cornerindex]);
10487 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10489 // convert vertex positions to texcoords
10490 Matrix4x4_Transform(projection, v[cornerindex], temp);
10491 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10492 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10493 // calculate distance fade from the projection origin
10494 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10495 f = bound(0.0f, f, 1.0f);
10496 c[cornerindex][0] = r * f;
10497 c[cornerindex][1] = g * f;
10498 c[cornerindex][2] = b * f;
10499 c[cornerindex][3] = 1.0f;
10500 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10503 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);
10505 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10506 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);
10508 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)
10510 matrix4x4_t projection;
10511 decalsystem_t *decalsystem;
10514 const msurface_t *surface;
10515 const msurface_t *surfaces;
10516 const int *surfacelist;
10517 const texture_t *texture;
10519 int numsurfacelist;
10520 int surfacelistindex;
10523 float localorigin[3];
10524 float localnormal[3];
10525 float localmins[3];
10526 float localmaxs[3];
10529 float planes[6][4];
10532 int bih_triangles_count;
10533 int bih_triangles[256];
10534 int bih_surfaces[256];
10536 decalsystem = &ent->decalsystem;
10537 model = ent->model;
10538 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10540 R_DecalSystem_Reset(&ent->decalsystem);
10544 if (!model->brush.data_leafs && !cl_decals_models.integer)
10546 if (decalsystem->model)
10547 R_DecalSystem_Reset(decalsystem);
10551 if (decalsystem->model != model)
10552 R_DecalSystem_Reset(decalsystem);
10553 decalsystem->model = model;
10555 RSurf_ActiveModelEntity(ent, true, false, false);
10557 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10558 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10559 VectorNormalize(localnormal);
10560 localsize = worldsize*rsurface.inversematrixscale;
10561 localmins[0] = localorigin[0] - localsize;
10562 localmins[1] = localorigin[1] - localsize;
10563 localmins[2] = localorigin[2] - localsize;
10564 localmaxs[0] = localorigin[0] + localsize;
10565 localmaxs[1] = localorigin[1] + localsize;
10566 localmaxs[2] = localorigin[2] + localsize;
10568 //VectorCopy(localnormal, planes[4]);
10569 //VectorVectors(planes[4], planes[2], planes[0]);
10570 AnglesFromVectors(angles, localnormal, NULL, false);
10571 AngleVectors(angles, planes[0], planes[2], planes[4]);
10572 VectorNegate(planes[0], planes[1]);
10573 VectorNegate(planes[2], planes[3]);
10574 VectorNegate(planes[4], planes[5]);
10575 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10576 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10577 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10578 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10579 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10580 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10585 matrix4x4_t forwardprojection;
10586 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10587 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10592 float projectionvector[4][3];
10593 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10594 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10595 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10596 projectionvector[0][0] = planes[0][0] * ilocalsize;
10597 projectionvector[0][1] = planes[1][0] * ilocalsize;
10598 projectionvector[0][2] = planes[2][0] * ilocalsize;
10599 projectionvector[1][0] = planes[0][1] * ilocalsize;
10600 projectionvector[1][1] = planes[1][1] * ilocalsize;
10601 projectionvector[1][2] = planes[2][1] * ilocalsize;
10602 projectionvector[2][0] = planes[0][2] * ilocalsize;
10603 projectionvector[2][1] = planes[1][2] * ilocalsize;
10604 projectionvector[2][2] = planes[2][2] * ilocalsize;
10605 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10606 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10607 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10608 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10612 dynamic = model->surfmesh.isanimated;
10613 numsurfacelist = model->nummodelsurfaces;
10614 surfacelist = model->sortedmodelsurfaces;
10615 surfaces = model->data_surfaces;
10618 bih_triangles_count = -1;
10621 if(model->render_bih.numleafs)
10622 bih = &model->render_bih;
10623 else if(model->collision_bih.numleafs)
10624 bih = &model->collision_bih;
10627 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10628 if(bih_triangles_count == 0)
10630 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10632 if(bih_triangles_count > 0)
10634 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10636 surfaceindex = bih_surfaces[triangleindex];
10637 surface = surfaces + surfaceindex;
10638 texture = surface->texture;
10639 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10641 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10643 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10648 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10650 surfaceindex = surfacelist[surfacelistindex];
10651 surface = surfaces + surfaceindex;
10652 // check cull box first because it rejects more than any other check
10653 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10655 // skip transparent surfaces
10656 texture = surface->texture;
10657 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10659 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10661 numtriangles = surface->num_triangles;
10662 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10663 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10668 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10669 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)
10671 int renderentityindex;
10672 float worldmins[3];
10673 float worldmaxs[3];
10674 entity_render_t *ent;
10676 if (!cl_decals_newsystem.integer)
10679 worldmins[0] = worldorigin[0] - worldsize;
10680 worldmins[1] = worldorigin[1] - worldsize;
10681 worldmins[2] = worldorigin[2] - worldsize;
10682 worldmaxs[0] = worldorigin[0] + worldsize;
10683 worldmaxs[1] = worldorigin[1] + worldsize;
10684 worldmaxs[2] = worldorigin[2] + worldsize;
10686 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10688 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10690 ent = r_refdef.scene.entities[renderentityindex];
10691 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10694 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10698 typedef struct r_decalsystem_splatqueue_s
10700 vec3_t worldorigin;
10701 vec3_t worldnormal;
10707 r_decalsystem_splatqueue_t;
10709 int r_decalsystem_numqueued = 0;
10710 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10712 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)
10714 r_decalsystem_splatqueue_t *queue;
10716 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10719 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10720 VectorCopy(worldorigin, queue->worldorigin);
10721 VectorCopy(worldnormal, queue->worldnormal);
10722 Vector4Set(queue->color, r, g, b, a);
10723 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10724 queue->worldsize = worldsize;
10725 queue->decalsequence = cl.decalsequence++;
10728 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10731 r_decalsystem_splatqueue_t *queue;
10733 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10734 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);
10735 r_decalsystem_numqueued = 0;
10738 extern cvar_t cl_decals_max;
10739 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10742 decalsystem_t *decalsystem = &ent->decalsystem;
10749 if (!decalsystem->numdecals)
10752 if (r_showsurfaces.integer)
10755 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10757 R_DecalSystem_Reset(decalsystem);
10761 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10762 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10764 if (decalsystem->lastupdatetime)
10765 frametime = (cl.time - decalsystem->lastupdatetime);
10768 decalsystem->lastupdatetime = cl.time;
10769 decal = decalsystem->decals;
10770 numdecals = decalsystem->numdecals;
10772 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10774 if (decal->color4f[0][3])
10776 decal->lived += frametime;
10777 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10779 memset(decal, 0, sizeof(*decal));
10780 if (decalsystem->freedecal > i)
10781 decalsystem->freedecal = i;
10785 decal = decalsystem->decals;
10786 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10789 // collapse the array by shuffling the tail decals into the gaps
10792 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10793 decalsystem->freedecal++;
10794 if (decalsystem->freedecal == numdecals)
10796 decal[decalsystem->freedecal] = decal[--numdecals];
10799 decalsystem->numdecals = numdecals;
10801 if (numdecals <= 0)
10803 // if there are no decals left, reset decalsystem
10804 R_DecalSystem_Reset(decalsystem);
10808 extern skinframe_t *decalskinframe;
10809 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10812 decalsystem_t *decalsystem = &ent->decalsystem;
10821 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10824 numdecals = decalsystem->numdecals;
10828 if (r_showsurfaces.integer)
10831 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10833 R_DecalSystem_Reset(decalsystem);
10837 // if the model is static it doesn't matter what value we give for
10838 // wantnormals and wanttangents, so this logic uses only rules applicable
10839 // to a model, knowing that they are meaningless otherwise
10840 if (ent == r_refdef.scene.worldentity)
10841 RSurf_ActiveWorldEntity();
10843 RSurf_ActiveModelEntity(ent, false, false, false);
10845 decalsystem->lastupdatetime = cl.time;
10846 decal = decalsystem->decals;
10848 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10850 // update vertex positions for animated models
10851 v3f = decalsystem->vertex3f;
10852 c4f = decalsystem->color4f;
10853 t2f = decalsystem->texcoord2f;
10854 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10856 if (!decal->color4f[0][3])
10859 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10863 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10866 // update color values for fading decals
10867 if (decal->lived >= cl_decals_time.value)
10868 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10872 c4f[ 0] = decal->color4f[0][0] * alpha;
10873 c4f[ 1] = decal->color4f[0][1] * alpha;
10874 c4f[ 2] = decal->color4f[0][2] * alpha;
10876 c4f[ 4] = decal->color4f[1][0] * alpha;
10877 c4f[ 5] = decal->color4f[1][1] * alpha;
10878 c4f[ 6] = decal->color4f[1][2] * alpha;
10880 c4f[ 8] = decal->color4f[2][0] * alpha;
10881 c4f[ 9] = decal->color4f[2][1] * alpha;
10882 c4f[10] = decal->color4f[2][2] * alpha;
10885 t2f[0] = decal->texcoord2f[0][0];
10886 t2f[1] = decal->texcoord2f[0][1];
10887 t2f[2] = decal->texcoord2f[1][0];
10888 t2f[3] = decal->texcoord2f[1][1];
10889 t2f[4] = decal->texcoord2f[2][0];
10890 t2f[5] = decal->texcoord2f[2][1];
10892 // update vertex positions for animated models
10893 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10895 e = rsurface.modelelement3i + 3*decal->triangleindex;
10896 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10897 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10898 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10902 VectorCopy(decal->vertex3f[0], v3f);
10903 VectorCopy(decal->vertex3f[1], v3f + 3);
10904 VectorCopy(decal->vertex3f[2], v3f + 6);
10907 if (r_refdef.fogenabled)
10909 alpha = RSurf_FogVertex(v3f);
10910 VectorScale(c4f, alpha, c4f);
10911 alpha = RSurf_FogVertex(v3f + 3);
10912 VectorScale(c4f + 4, alpha, c4f + 4);
10913 alpha = RSurf_FogVertex(v3f + 6);
10914 VectorScale(c4f + 8, alpha, c4f + 8);
10925 r_refdef.stats.drawndecals += numtris;
10927 // now render the decals all at once
10928 // (this assumes they all use one particle font texture!)
10929 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);
10930 // R_Mesh_ResetTextureState();
10931 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10932 GL_DepthMask(false);
10933 GL_DepthRange(0, 1);
10934 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10935 GL_DepthTest(true);
10936 GL_CullFace(GL_NONE);
10937 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10938 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10939 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10943 static void R_DrawModelDecals(void)
10947 // fade faster when there are too many decals
10948 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10949 for (i = 0;i < r_refdef.scene.numentities;i++)
10950 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10952 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10953 for (i = 0;i < r_refdef.scene.numentities;i++)
10954 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10955 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10957 R_DecalSystem_ApplySplatEntitiesQueue();
10959 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10960 for (i = 0;i < r_refdef.scene.numentities;i++)
10961 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10963 r_refdef.stats.totaldecals += numdecals;
10965 if (r_showsurfaces.integer)
10968 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10970 for (i = 0;i < r_refdef.scene.numentities;i++)
10972 if (!r_refdef.viewcache.entityvisible[i])
10974 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10975 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10979 extern cvar_t mod_collision_bih;
10980 void R_DrawDebugModel(void)
10982 entity_render_t *ent = rsurface.entity;
10983 int i, j, k, l, flagsmask;
10984 const msurface_t *surface;
10985 dp_model_t *model = ent->model;
10988 switch(vid.renderpath)
10990 case RENDERPATH_GL11:
10991 case RENDERPATH_GL13:
10992 case RENDERPATH_GL20:
10994 case RENDERPATH_D3D9:
10995 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10997 case RENDERPATH_D3D10:
10998 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11000 case RENDERPATH_D3D11:
11001 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11003 case RENDERPATH_SOFT:
11004 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11006 case RENDERPATH_GLES2:
11007 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11011 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11013 // R_Mesh_ResetTextureState();
11014 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11015 GL_DepthRange(0, 1);
11016 GL_DepthTest(!r_showdisabledepthtest.integer);
11017 GL_DepthMask(false);
11018 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11020 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11024 qboolean cullbox = ent == r_refdef.scene.worldentity;
11025 const q3mbrush_t *brush;
11026 const bih_t *bih = &model->collision_bih;
11027 const bih_leaf_t *bihleaf;
11028 float vertex3f[3][3];
11029 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11031 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11033 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11035 switch (bihleaf->type)
11038 brush = model->brush.data_brushes + bihleaf->itemindex;
11039 if (brush->colbrushf && brush->colbrushf->numtriangles)
11041 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);
11042 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11043 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11046 case BIH_COLLISIONTRIANGLE:
11047 triangleindex = bihleaf->itemindex;
11048 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11049 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11050 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11051 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);
11052 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11053 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11055 case BIH_RENDERTRIANGLE:
11056 triangleindex = bihleaf->itemindex;
11057 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11058 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11059 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11060 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);
11061 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11062 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11068 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11070 if (r_showtris.integer || (r_shownormals.value != 0))
11072 if (r_showdisabledepthtest.integer)
11074 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11075 GL_DepthMask(false);
11079 GL_BlendFunc(GL_ONE, GL_ZERO);
11080 GL_DepthMask(true);
11082 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11084 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11086 rsurface.texture = R_GetCurrentTexture(surface->texture);
11087 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11089 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11090 if (r_showtris.value > 0)
11092 if (!rsurface.texture->currentlayers->depthmask)
11093 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11094 else if (ent == r_refdef.scene.worldentity)
11095 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11097 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11098 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11099 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11101 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11104 if (r_shownormals.value < 0)
11106 qglBegin(GL_LINES);
11107 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11109 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11110 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11111 qglVertex3f(v[0], v[1], v[2]);
11112 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11113 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11114 qglVertex3f(v[0], v[1], v[2]);
11119 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11121 qglBegin(GL_LINES);
11122 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11124 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11125 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11126 qglVertex3f(v[0], v[1], v[2]);
11127 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11128 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11129 qglVertex3f(v[0], v[1], v[2]);
11133 qglBegin(GL_LINES);
11134 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11136 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11137 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11138 qglVertex3f(v[0], v[1], v[2]);
11139 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11140 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11141 qglVertex3f(v[0], v[1], v[2]);
11145 qglBegin(GL_LINES);
11146 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11148 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11149 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11150 qglVertex3f(v[0], v[1], v[2]);
11151 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11152 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11153 qglVertex3f(v[0], v[1], v[2]);
11160 rsurface.texture = NULL;
11164 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11165 int r_maxsurfacelist = 0;
11166 const msurface_t **r_surfacelist = NULL;
11167 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11169 int i, j, endj, flagsmask;
11170 dp_model_t *model = r_refdef.scene.worldmodel;
11171 msurface_t *surfaces;
11172 unsigned char *update;
11173 int numsurfacelist = 0;
11177 if (r_maxsurfacelist < model->num_surfaces)
11179 r_maxsurfacelist = model->num_surfaces;
11181 Mem_Free((msurface_t**)r_surfacelist);
11182 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11185 RSurf_ActiveWorldEntity();
11187 surfaces = model->data_surfaces;
11188 update = model->brushq1.lightmapupdateflags;
11190 // update light styles on this submodel
11191 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11193 model_brush_lightstyleinfo_t *style;
11194 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11196 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11198 int *list = style->surfacelist;
11199 style->value = r_refdef.scene.lightstylevalue[style->style];
11200 for (j = 0;j < style->numsurfaces;j++)
11201 update[list[j]] = true;
11206 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11210 R_DrawDebugModel();
11211 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11215 rsurface.lightmaptexture = NULL;
11216 rsurface.deluxemaptexture = NULL;
11217 rsurface.uselightmaptexture = false;
11218 rsurface.texture = NULL;
11219 rsurface.rtlight = NULL;
11220 numsurfacelist = 0;
11221 // add visible surfaces to draw list
11222 for (i = 0;i < model->nummodelsurfaces;i++)
11224 j = model->sortedmodelsurfaces[i];
11225 if (r_refdef.viewcache.world_surfacevisible[j])
11226 r_surfacelist[numsurfacelist++] = surfaces + j;
11228 // update lightmaps if needed
11229 if (model->brushq1.firstrender)
11231 model->brushq1.firstrender = false;
11232 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11234 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11238 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11239 if (r_refdef.viewcache.world_surfacevisible[j])
11241 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11243 // don't do anything if there were no surfaces
11244 if (!numsurfacelist)
11246 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11249 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11251 // add to stats if desired
11252 if (r_speeds.integer && !skysurfaces && !depthonly)
11254 r_refdef.stats.world_surfaces += numsurfacelist;
11255 for (j = 0;j < numsurfacelist;j++)
11256 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11259 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11262 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11264 int i, j, endj, flagsmask;
11265 dp_model_t *model = ent->model;
11266 msurface_t *surfaces;
11267 unsigned char *update;
11268 int numsurfacelist = 0;
11272 if (r_maxsurfacelist < model->num_surfaces)
11274 r_maxsurfacelist = model->num_surfaces;
11276 Mem_Free((msurface_t **)r_surfacelist);
11277 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11280 // if the model is static it doesn't matter what value we give for
11281 // wantnormals and wanttangents, so this logic uses only rules applicable
11282 // to a model, knowing that they are meaningless otherwise
11283 if (ent == r_refdef.scene.worldentity)
11284 RSurf_ActiveWorldEntity();
11285 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11286 RSurf_ActiveModelEntity(ent, false, false, false);
11288 RSurf_ActiveModelEntity(ent, true, true, true);
11289 else if (depthonly)
11291 switch (vid.renderpath)
11293 case RENDERPATH_GL20:
11294 case RENDERPATH_D3D9:
11295 case RENDERPATH_D3D10:
11296 case RENDERPATH_D3D11:
11297 case RENDERPATH_SOFT:
11298 case RENDERPATH_GLES2:
11299 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11301 case RENDERPATH_GL13:
11302 case RENDERPATH_GL11:
11303 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11309 switch (vid.renderpath)
11311 case RENDERPATH_GL20:
11312 case RENDERPATH_D3D9:
11313 case RENDERPATH_D3D10:
11314 case RENDERPATH_D3D11:
11315 case RENDERPATH_SOFT:
11316 case RENDERPATH_GLES2:
11317 RSurf_ActiveModelEntity(ent, true, true, false);
11319 case RENDERPATH_GL13:
11320 case RENDERPATH_GL11:
11321 RSurf_ActiveModelEntity(ent, true, false, false);
11326 surfaces = model->data_surfaces;
11327 update = model->brushq1.lightmapupdateflags;
11329 // update light styles
11330 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11332 model_brush_lightstyleinfo_t *style;
11333 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11335 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11337 int *list = style->surfacelist;
11338 style->value = r_refdef.scene.lightstylevalue[style->style];
11339 for (j = 0;j < style->numsurfaces;j++)
11340 update[list[j]] = true;
11345 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11349 R_DrawDebugModel();
11350 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11354 rsurface.lightmaptexture = NULL;
11355 rsurface.deluxemaptexture = NULL;
11356 rsurface.uselightmaptexture = false;
11357 rsurface.texture = NULL;
11358 rsurface.rtlight = NULL;
11359 numsurfacelist = 0;
11360 // add visible surfaces to draw list
11361 for (i = 0;i < model->nummodelsurfaces;i++)
11362 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11363 // don't do anything if there were no surfaces
11364 if (!numsurfacelist)
11366 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11369 // update lightmaps if needed
11373 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11378 R_BuildLightMap(ent, surfaces + j);
11383 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11385 R_BuildLightMap(ent, surfaces + j);
11386 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11388 // add to stats if desired
11389 if (r_speeds.integer && !skysurfaces && !depthonly)
11391 r_refdef.stats.entities_surfaces += numsurfacelist;
11392 for (j = 0;j < numsurfacelist;j++)
11393 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11396 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11399 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11401 static texture_t texture;
11402 static msurface_t surface;
11403 const msurface_t *surfacelist = &surface;
11405 // fake enough texture and surface state to render this geometry
11407 texture.update_lastrenderframe = -1; // regenerate this texture
11408 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11409 texture.currentskinframe = skinframe;
11410 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11411 texture.offsetmapping = OFFSETMAPPING_OFF;
11412 texture.offsetscale = 1;
11413 texture.specularscalemod = 1;
11414 texture.specularpowermod = 1;
11416 surface.texture = &texture;
11417 surface.num_triangles = numtriangles;
11418 surface.num_firsttriangle = firsttriangle;
11419 surface.num_vertices = numvertices;
11420 surface.num_firstvertex = firstvertex;
11423 rsurface.texture = R_GetCurrentTexture(surface.texture);
11424 rsurface.lightmaptexture = NULL;
11425 rsurface.deluxemaptexture = NULL;
11426 rsurface.uselightmaptexture = false;
11427 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11430 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)
11432 static msurface_t surface;
11433 const msurface_t *surfacelist = &surface;
11435 // fake enough texture and surface state to render this geometry
11436 surface.texture = texture;
11437 surface.num_triangles = numtriangles;
11438 surface.num_firsttriangle = firsttriangle;
11439 surface.num_vertices = numvertices;
11440 surface.num_firstvertex = firstvertex;
11443 rsurface.texture = R_GetCurrentTexture(surface.texture);
11444 rsurface.lightmaptexture = NULL;
11445 rsurface.deluxemaptexture = NULL;
11446 rsurface.uselightmaptexture = false;
11447 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);