2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_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"};
145 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"};
147 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)"};
148 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
149 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)"};
150 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
151 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)"};
152 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
153 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158 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)"};
159 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)"};
160 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)"};
161 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)"};
163 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)"};
164 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
165 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"};
166 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
167 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
168 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
170 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
171 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
172 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
173 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
175 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
176 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
177 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
178 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
179 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
180 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
181 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
183 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
184 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
185 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
186 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)"};
187 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
188 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
189 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
190 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
191 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
192 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
194 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"};
196 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"};
198 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
200 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
201 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"};
202 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
203 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
204 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
205 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
206 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)"};
207 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
208 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 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"};
213 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."};
215 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)"};
217 extern cvar_t v_glslgamma;
219 extern qboolean v_flipped_state;
221 static struct r_bloomstate_s
226 int bloomwidth, bloomheight;
228 textype_t texturetype;
229 int viewfbo; // used to check if r_viewfbo cvar has changed
231 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
235 int screentexturewidth, screentextureheight;
236 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
238 int bloomtexturewidth, bloomtextureheight;
239 rtexture_t *texture_bloom;
241 // arrays for rendering the screen passes
242 float screentexcoord2f[8];
243 float bloomtexcoord2f[8];
244 float offsettexcoord2f[8];
246 r_viewport_t viewport;
250 r_waterstate_t r_waterstate;
252 /// shadow volume bsp struct with automatically growing nodes buffer
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
277 int r_texture_numcubemaps;
278 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
284 typedef struct r_qwskincache_s
286 char name[MAX_QPATH];
287 skinframe_t *skinframe;
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
304 const float r_d3dscreenvertex3f[12] =
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
315 for (i = 0;i < verts;i++)
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
329 for (i = 0;i < verts;i++)
339 // FIXME: move this to client?
342 if (gamemode == GAME_NEHAHRA)
344 Cvar_Set("gl_fogenable", "0");
345 Cvar_Set("gl_fogdensity", "0.2");
346 Cvar_Set("gl_fogred", "0.3");
347 Cvar_Set("gl_foggreen", "0.3");
348 Cvar_Set("gl_fogblue", "0.3");
350 r_refdef.fog_density = 0;
351 r_refdef.fog_red = 0;
352 r_refdef.fog_green = 0;
353 r_refdef.fog_blue = 0;
354 r_refdef.fog_alpha = 1;
355 r_refdef.fog_start = 0;
356 r_refdef.fog_end = 16384;
357 r_refdef.fog_height = 1<<30;
358 r_refdef.fog_fadedepth = 128;
359 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
362 static void R_BuildBlankTextures(void)
364 unsigned char data[4];
365 data[2] = 128; // normal X
366 data[1] = 128; // normal Y
367 data[0] = 255; // normal Z
368 data[3] = 128; // height
369 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildNoTexture(void)
390 unsigned char pix[16][16][4];
391 // this makes a light grey/dark grey checkerboard texture
392 for (y = 0;y < 16;y++)
394 for (x = 0;x < 16;x++)
396 if ((y < 8) ^ (x < 8))
412 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
415 static void R_BuildWhiteCube(void)
417 unsigned char data[6*1*1*4];
418 memset(data, 255, sizeof(data));
419 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildNormalizationCube(void)
426 vec_t s, t, intensity;
429 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430 for (side = 0;side < 6;side++)
432 for (y = 0;y < NORMSIZE;y++)
434 for (x = 0;x < NORMSIZE;x++)
436 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
472 intensity = 127.0f / sqrt(DotProduct(v, v));
473 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476 data[((side*64+y)*64+x)*4+3] = 255;
480 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
484 static void R_BuildFogTexture(void)
488 unsigned char data1[FOGWIDTH][4];
489 //unsigned char data2[FOGWIDTH][4];
492 r_refdef.fogmasktable_start = r_refdef.fog_start;
493 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494 r_refdef.fogmasktable_range = r_refdef.fogrange;
495 r_refdef.fogmasktable_density = r_refdef.fog_density;
497 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
500 d = (x * r - r_refdef.fogmasktable_start);
501 if(developer_extra.integer)
502 Con_DPrintf("%f ", d);
504 if (r_fog_exp2.integer)
505 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
507 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508 if(developer_extra.integer)
509 Con_DPrintf(" : %f ", alpha);
510 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511 if(developer_extra.integer)
512 Con_DPrintf(" = %f\n", alpha);
513 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
516 for (x = 0;x < FOGWIDTH;x++)
518 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
523 //data2[x][0] = 255 - b;
524 //data2[x][1] = 255 - b;
525 //data2[x][2] = 255 - b;
528 if (r_texture_fogattenuation)
530 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
535 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
540 static void R_BuildFogHeightTexture(void)
542 unsigned char *inpixels;
550 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551 if (r_refdef.fogheighttexturename[0])
552 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
555 r_refdef.fog_height_tablesize = 0;
556 if (r_texture_fogheighttexture)
557 R_FreeTexture(r_texture_fogheighttexture);
558 r_texture_fogheighttexture = NULL;
559 if (r_refdef.fog_height_table2d)
560 Mem_Free(r_refdef.fog_height_table2d);
561 r_refdef.fog_height_table2d = NULL;
562 if (r_refdef.fog_height_table1d)
563 Mem_Free(r_refdef.fog_height_table1d);
564 r_refdef.fog_height_table1d = NULL;
568 r_refdef.fog_height_tablesize = size;
569 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
573 // LordHavoc: now the magic - what is that table2d for? it is a cooked
574 // average fog color table accounting for every fog layer between a point
575 // and the camera. (Note: attenuation is handled separately!)
576 for (y = 0;y < size;y++)
578 for (x = 0;x < size;x++)
584 for (j = x;j <= y;j++)
586 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592 for (j = x;j >= y;j--)
594 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
605 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
608 //=======================================================================================================================================================
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
621 //=======================================================================================================================================================
623 typedef struct shaderpermutationinfo_s
628 shaderpermutationinfo_t;
630 typedef struct shadermodeinfo_s
632 const char *vertexfilename;
633 const char *geometryfilename;
634 const char *fragmentfilename;
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
643 {"#define USEDIFFUSE\n", " diffuse"},
644 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645 {"#define USEVIEWTINT\n", " viewtint"},
646 {"#define USECOLORMAPPING\n", " colormapping"},
647 {"#define USESATURATION\n", " saturation"},
648 {"#define USEFOGINSIDE\n", " foginside"},
649 {"#define USEFOGOUTSIDE\n", " fogoutside"},
650 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652 {"#define USEGAMMARAMPS\n", " gammaramps"},
653 {"#define USECUBEFILTER\n", " cubefilter"},
654 {"#define USEGLOW\n", " glow"},
655 {"#define USEBLOOM\n", " bloom"},
656 {"#define USESPECULAR\n", " specular"},
657 {"#define USEPOSTPROCESSING\n", " postprocessing"},
658 {"#define USEREFLECTION\n", " reflection"},
659 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668 {"#define USEALPHAKILL\n", " alphakill"},
669 {"#define USEREFLECTCUBE\n", " reflectcube"},
670 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671 {"#define USEBOUNCEGRID\n", " bouncegrid"},
672 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
675 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
676 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
680 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
696 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
720 struct r_glsl_permutation_s *hashnext;
722 unsigned int permutation;
724 /// indicates if we have tried compiling this permutation already
726 /// 0 if compilation failed
728 // texture units assigned to each detected uniform
729 int tex_Texture_First;
730 int tex_Texture_Second;
731 int tex_Texture_GammaRamps;
732 int tex_Texture_Normal;
733 int tex_Texture_Color;
734 int tex_Texture_Gloss;
735 int tex_Texture_Glow;
736 int tex_Texture_SecondaryNormal;
737 int tex_Texture_SecondaryColor;
738 int tex_Texture_SecondaryGloss;
739 int tex_Texture_SecondaryGlow;
740 int tex_Texture_Pants;
741 int tex_Texture_Shirt;
742 int tex_Texture_FogHeightTexture;
743 int tex_Texture_FogMask;
744 int tex_Texture_Lightmap;
745 int tex_Texture_Deluxemap;
746 int tex_Texture_Attenuation;
747 int tex_Texture_Cube;
748 int tex_Texture_Refraction;
749 int tex_Texture_Reflection;
750 int tex_Texture_ShadowMap2D;
751 int tex_Texture_CubeProjection;
752 int tex_Texture_ScreenDepth;
753 int tex_Texture_ScreenNormalMap;
754 int tex_Texture_ScreenDiffuse;
755 int tex_Texture_ScreenSpecular;
756 int tex_Texture_ReflectMask;
757 int tex_Texture_ReflectCube;
758 int tex_Texture_BounceGrid;
759 /// locations of detected uniforms in program object, or -1 if not found
760 int loc_Texture_First;
761 int loc_Texture_Second;
762 int loc_Texture_GammaRamps;
763 int loc_Texture_Normal;
764 int loc_Texture_Color;
765 int loc_Texture_Gloss;
766 int loc_Texture_Glow;
767 int loc_Texture_SecondaryNormal;
768 int loc_Texture_SecondaryColor;
769 int loc_Texture_SecondaryGloss;
770 int loc_Texture_SecondaryGlow;
771 int loc_Texture_Pants;
772 int loc_Texture_Shirt;
773 int loc_Texture_FogHeightTexture;
774 int loc_Texture_FogMask;
775 int loc_Texture_Lightmap;
776 int loc_Texture_Deluxemap;
777 int loc_Texture_Attenuation;
778 int loc_Texture_Cube;
779 int loc_Texture_Refraction;
780 int loc_Texture_Reflection;
781 int loc_Texture_ShadowMap2D;
782 int loc_Texture_CubeProjection;
783 int loc_Texture_ScreenDepth;
784 int loc_Texture_ScreenNormalMap;
785 int loc_Texture_ScreenDiffuse;
786 int loc_Texture_ScreenSpecular;
787 int loc_Texture_ReflectMask;
788 int loc_Texture_ReflectCube;
789 int loc_Texture_BounceGrid;
791 int loc_BloomBlur_Parameters;
793 int loc_Color_Ambient;
794 int loc_Color_Diffuse;
795 int loc_Color_Specular;
799 int loc_DeferredColor_Ambient;
800 int loc_DeferredColor_Diffuse;
801 int loc_DeferredColor_Specular;
802 int loc_DeferredMod_Diffuse;
803 int loc_DeferredMod_Specular;
804 int loc_DistortScaleRefractReflect;
807 int loc_FogHeightFade;
809 int loc_FogPlaneViewDist;
810 int loc_FogRangeRecip;
813 int loc_LightPosition;
814 int loc_OffsetMapping_ScaleSteps;
816 int loc_ReflectColor;
817 int loc_ReflectFactor;
818 int loc_ReflectOffset;
819 int loc_RefractColor;
821 int loc_ScreenCenterRefractReflect;
822 int loc_ScreenScaleRefractReflect;
823 int loc_ScreenToDepth;
824 int loc_ShadowMap_Parameters;
825 int loc_ShadowMap_TextureScale;
826 int loc_SpecularPower;
831 int loc_ViewTintColor;
833 int loc_ModelToLight;
835 int loc_BackgroundTexMatrix;
836 int loc_ModelViewProjectionMatrix;
837 int loc_ModelViewMatrix;
838 int loc_PixelToScreenTexCoord;
839 int loc_ModelToReflectCube;
840 int loc_ShadowMapMatrix;
841 int loc_BloomColorSubtract;
842 int loc_NormalmapScrollBlend;
843 int loc_BounceGridMatrix;
844 int loc_BounceGridIntensity;
846 r_glsl_permutation_t;
848 #define SHADERPERMUTATION_HASHSIZE 256
851 // non-degradable "lightweight" shader parameters to keep the permutations simpler
852 // these can NOT degrade! only use for simple stuff
855 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
856 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
857 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
858 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
859 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
860 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
861 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
863 #define SHADERSTATICPARMS_COUNT 7
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870 qboolean R_CompileShader_CheckStaticParms(void)
872 static int r_compileshader_staticparms_save[1];
873 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
874 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
877 if (r_glsl_saturation_redcompensate.integer)
878 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
879 if (r_glsl_vertextextureblend_usebothalphas.integer)
880 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
881 if (r_shadow_glossexact.integer)
882 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
883 if (r_glsl_postprocess.integer)
885 if (r_glsl_postprocess_uservec1_enable.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
887 if (r_glsl_postprocess_uservec2_enable.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
889 if (r_glsl_postprocess_uservec3_enable.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
891 if (r_glsl_postprocess_uservec4_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
897 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
898 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
899 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
901 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
902 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
904 shaderstaticparms_count = 0;
907 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
908 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
909 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
910 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
911 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
912 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
916 /// information about each possible shader permutation
917 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
918 /// currently selected permutation
919 r_glsl_permutation_t *r_glsl_permutation;
920 /// storage for permutations linked in the hash table
921 memexpandablearray_t r_glsl_permutationarray;
923 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
925 //unsigned int hashdepth = 0;
926 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
927 r_glsl_permutation_t *p;
928 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
930 if (p->mode == mode && p->permutation == permutation)
932 //if (hashdepth > 10)
933 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
938 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
940 p->permutation = permutation;
941 p->hashnext = r_glsl_permutationhash[mode][hashindex];
942 r_glsl_permutationhash[mode][hashindex] = p;
943 //if (hashdepth > 10)
944 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
948 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
951 if (!filename || !filename[0])
953 if (!strcmp(filename, "glsl/default.glsl"))
955 if (!glslshaderstring)
957 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958 if (glslshaderstring)
959 Con_DPrintf("Loading shaders from file %s...\n", filename);
961 glslshaderstring = (char *)builtinshaderstring;
963 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
964 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
967 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970 if (printfromdisknotice)
971 Con_DPrintf("from disk %s... ", filename);
977 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
981 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
982 char *vertexstring, *geometrystring, *fragmentstring;
983 char permutationname[256];
984 int vertstrings_count = 0;
985 int geomstrings_count = 0;
986 int fragstrings_count = 0;
987 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
988 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996 permutationname[0] = 0;
997 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
998 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
999 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1001 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1003 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1004 if(vid.support.gl20shaders130)
1006 vertstrings_list[vertstrings_count++] = "#version 130\n";
1007 geomstrings_list[geomstrings_count++] = "#version 130\n";
1008 fragstrings_list[fragstrings_count++] = "#version 130\n";
1009 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1010 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1011 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1014 // the first pretext is which type of shader to compile as
1015 // (later these will all be bound together as a program object)
1016 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1017 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1018 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1020 // the second pretext is the mode (for example a light source)
1021 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1022 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1023 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1024 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1026 // now add all the permutation pretexts
1027 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1029 if (permutation & (1<<i))
1031 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1032 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1033 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1034 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1038 // keep line numbers correct
1039 vertstrings_list[vertstrings_count++] = "\n";
1040 geomstrings_list[geomstrings_count++] = "\n";
1041 fragstrings_list[fragstrings_count++] = "\n";
1046 R_CompileShader_AddStaticParms(mode, permutation);
1047 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1048 vertstrings_count += shaderstaticparms_count;
1049 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050 geomstrings_count += shaderstaticparms_count;
1051 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052 fragstrings_count += shaderstaticparms_count;
1054 // now append the shader text itself
1055 vertstrings_list[vertstrings_count++] = vertexstring;
1056 geomstrings_list[geomstrings_count++] = geometrystring;
1057 fragstrings_list[fragstrings_count++] = fragmentstring;
1059 // if any sources were NULL, clear the respective list
1061 vertstrings_count = 0;
1062 if (!geometrystring)
1063 geomstrings_count = 0;
1064 if (!fragmentstring)
1065 fragstrings_count = 0;
1067 // compile the shader program
1068 if (vertstrings_count + geomstrings_count + fragstrings_count)
1069 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1073 qglUseProgram(p->program);CHECKGLERROR
1074 // look up all the uniform variable names we care about, so we don't
1075 // have to look them up every time we set them
1077 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1078 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1079 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1080 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1081 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1082 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1083 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1084 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1085 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1086 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1087 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1088 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1089 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1090 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1091 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1092 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1093 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1094 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1095 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1096 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1097 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1098 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1099 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1100 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1101 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1102 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1103 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1104 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1105 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1106 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1107 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1108 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1109 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1110 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1111 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1112 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1113 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1114 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1115 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1116 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1117 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1118 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1119 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1120 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1121 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1122 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1123 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1124 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1125 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1126 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1127 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1128 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1129 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1130 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1131 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1132 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1133 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1134 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1135 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1136 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1137 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1138 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1139 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1140 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1141 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1142 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1143 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1144 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1145 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1146 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1147 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1148 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1149 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1150 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1151 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1152 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1153 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1154 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1155 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1156 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1157 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1158 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1159 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1160 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1161 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1162 // initialize the samplers to refer to the texture units we use
1163 p->tex_Texture_First = -1;
1164 p->tex_Texture_Second = -1;
1165 p->tex_Texture_GammaRamps = -1;
1166 p->tex_Texture_Normal = -1;
1167 p->tex_Texture_Color = -1;
1168 p->tex_Texture_Gloss = -1;
1169 p->tex_Texture_Glow = -1;
1170 p->tex_Texture_SecondaryNormal = -1;
1171 p->tex_Texture_SecondaryColor = -1;
1172 p->tex_Texture_SecondaryGloss = -1;
1173 p->tex_Texture_SecondaryGlow = -1;
1174 p->tex_Texture_Pants = -1;
1175 p->tex_Texture_Shirt = -1;
1176 p->tex_Texture_FogHeightTexture = -1;
1177 p->tex_Texture_FogMask = -1;
1178 p->tex_Texture_Lightmap = -1;
1179 p->tex_Texture_Deluxemap = -1;
1180 p->tex_Texture_Attenuation = -1;
1181 p->tex_Texture_Cube = -1;
1182 p->tex_Texture_Refraction = -1;
1183 p->tex_Texture_Reflection = -1;
1184 p->tex_Texture_ShadowMap2D = -1;
1185 p->tex_Texture_CubeProjection = -1;
1186 p->tex_Texture_ScreenDepth = -1;
1187 p->tex_Texture_ScreenNormalMap = -1;
1188 p->tex_Texture_ScreenDiffuse = -1;
1189 p->tex_Texture_ScreenSpecular = -1;
1190 p->tex_Texture_ReflectMask = -1;
1191 p->tex_Texture_ReflectCube = -1;
1192 p->tex_Texture_BounceGrid = -1;
1194 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1195 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1196 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1197 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1198 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1199 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1200 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1201 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1202 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1203 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1204 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1205 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1206 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1207 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1208 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1209 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1210 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1211 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1212 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1213 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1214 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1215 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1216 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1217 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1218 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1219 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1220 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1221 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1222 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1223 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1225 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1228 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1232 Mem_Free(vertexstring);
1234 Mem_Free(geometrystring);
1236 Mem_Free(fragmentstring);
1239 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1241 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1242 if (r_glsl_permutation != perm)
1244 r_glsl_permutation = perm;
1245 if (!r_glsl_permutation->program)
1247 if (!r_glsl_permutation->compiled)
1248 R_GLSL_CompilePermutation(perm, mode, permutation);
1249 if (!r_glsl_permutation->program)
1251 // remove features until we find a valid permutation
1253 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1255 // reduce i more quickly whenever it would not remove any bits
1256 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1257 if (!(permutation & j))
1260 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1261 if (!r_glsl_permutation->compiled)
1262 R_GLSL_CompilePermutation(perm, mode, permutation);
1263 if (r_glsl_permutation->program)
1266 if (i >= SHADERPERMUTATION_COUNT)
1268 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1269 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270 qglUseProgram(0);CHECKGLERROR
1271 return; // no bit left to clear, entire mode is broken
1276 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1278 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1279 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1280 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1288 extern D3DCAPS9 vid_d3d9caps;
1291 struct r_hlsl_permutation_s;
1292 typedef struct r_hlsl_permutation_s
1294 /// hash lookup data
1295 struct r_hlsl_permutation_s *hashnext;
1297 unsigned int permutation;
1299 /// indicates if we have tried compiling this permutation already
1301 /// NULL if compilation failed
1302 IDirect3DVertexShader9 *vertexshader;
1303 IDirect3DPixelShader9 *pixelshader;
1305 r_hlsl_permutation_t;
1307 typedef enum D3DVSREGISTER_e
1309 D3DVSREGISTER_TexMatrix = 0, // float4x4
1310 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1311 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1312 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1313 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1314 D3DVSREGISTER_ModelToLight = 20, // float4x4
1315 D3DVSREGISTER_EyePosition = 24,
1316 D3DVSREGISTER_FogPlane = 25,
1317 D3DVSREGISTER_LightDir = 26,
1318 D3DVSREGISTER_LightPosition = 27,
1322 typedef enum D3DPSREGISTER_e
1324 D3DPSREGISTER_Alpha = 0,
1325 D3DPSREGISTER_BloomBlur_Parameters = 1,
1326 D3DPSREGISTER_ClientTime = 2,
1327 D3DPSREGISTER_Color_Ambient = 3,
1328 D3DPSREGISTER_Color_Diffuse = 4,
1329 D3DPSREGISTER_Color_Specular = 5,
1330 D3DPSREGISTER_Color_Glow = 6,
1331 D3DPSREGISTER_Color_Pants = 7,
1332 D3DPSREGISTER_Color_Shirt = 8,
1333 D3DPSREGISTER_DeferredColor_Ambient = 9,
1334 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1335 D3DPSREGISTER_DeferredColor_Specular = 11,
1336 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1337 D3DPSREGISTER_DeferredMod_Specular = 13,
1338 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1339 D3DPSREGISTER_EyePosition = 15, // unused
1340 D3DPSREGISTER_FogColor = 16,
1341 D3DPSREGISTER_FogHeightFade = 17,
1342 D3DPSREGISTER_FogPlane = 18,
1343 D3DPSREGISTER_FogPlaneViewDist = 19,
1344 D3DPSREGISTER_FogRangeRecip = 20,
1345 D3DPSREGISTER_LightColor = 21,
1346 D3DPSREGISTER_LightDir = 22, // unused
1347 D3DPSREGISTER_LightPosition = 23,
1348 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1349 D3DPSREGISTER_PixelSize = 25,
1350 D3DPSREGISTER_ReflectColor = 26,
1351 D3DPSREGISTER_ReflectFactor = 27,
1352 D3DPSREGISTER_ReflectOffset = 28,
1353 D3DPSREGISTER_RefractColor = 29,
1354 D3DPSREGISTER_Saturation = 30,
1355 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1356 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1357 D3DPSREGISTER_ScreenToDepth = 33,
1358 D3DPSREGISTER_ShadowMap_Parameters = 34,
1359 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1360 D3DPSREGISTER_SpecularPower = 36,
1361 D3DPSREGISTER_UserVec1 = 37,
1362 D3DPSREGISTER_UserVec2 = 38,
1363 D3DPSREGISTER_UserVec3 = 39,
1364 D3DPSREGISTER_UserVec4 = 40,
1365 D3DPSREGISTER_ViewTintColor = 41,
1366 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1367 D3DPSREGISTER_BloomColorSubtract = 43,
1368 D3DPSREGISTER_ViewToLight = 44, // float4x4
1369 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1370 D3DPSREGISTER_NormalmapScrollBlend = 52,
1375 /// information about each possible shader permutation
1376 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1377 /// currently selected permutation
1378 r_hlsl_permutation_t *r_hlsl_permutation;
1379 /// storage for permutations linked in the hash table
1380 memexpandablearray_t r_hlsl_permutationarray;
1382 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1384 //unsigned int hashdepth = 0;
1385 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1386 r_hlsl_permutation_t *p;
1387 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1389 if (p->mode == mode && p->permutation == permutation)
1391 //if (hashdepth > 10)
1392 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1397 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1399 p->permutation = permutation;
1400 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1401 r_hlsl_permutationhash[mode][hashindex] = p;
1402 //if (hashdepth > 10)
1403 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1407 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1410 if (!filename || !filename[0])
1412 if (!strcmp(filename, "hlsl/default.hlsl"))
1414 if (!hlslshaderstring)
1416 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417 if (hlslshaderstring)
1418 Con_DPrintf("Loading shaders from file %s...\n", filename);
1420 hlslshaderstring = (char *)builtinhlslshaderstring;
1422 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1423 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1424 return shaderstring;
1426 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429 if (printfromdisknotice)
1430 Con_DPrintf("from disk %s... ", filename);
1431 return shaderstring;
1433 return shaderstring;
1437 //#include <d3dx9shader.h>
1438 //#include <d3dx9mesh.h>
1440 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1442 DWORD *vsbin = NULL;
1443 DWORD *psbin = NULL;
1444 fs_offset_t vsbinsize;
1445 fs_offset_t psbinsize;
1446 // IDirect3DVertexShader9 *vs = NULL;
1447 // IDirect3DPixelShader9 *ps = NULL;
1448 ID3DXBuffer *vslog = NULL;
1449 ID3DXBuffer *vsbuffer = NULL;
1450 ID3DXConstantTable *vsconstanttable = NULL;
1451 ID3DXBuffer *pslog = NULL;
1452 ID3DXBuffer *psbuffer = NULL;
1453 ID3DXConstantTable *psconstanttable = NULL;
1456 char temp[MAX_INPUTLINE];
1457 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1458 qboolean debugshader = gl_paranoid.integer != 0;
1459 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1463 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1464 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1466 if ((!vsbin && vertstring) || (!psbin && fragstring))
1468 const char* dllnames_d3dx9 [] =
1492 dllhandle_t d3dx9_dll = NULL;
1493 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1495 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496 dllfunction_t d3dx9_dllfuncs[] =
1498 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1499 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1500 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1503 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1505 DWORD shaderflags = 0;
1507 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1508 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1509 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1510 if (vertstring && vertstring[0])
1514 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1515 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1516 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1517 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1520 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1523 vsbinsize = vsbuffer->GetBufferSize();
1524 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1525 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1526 vsbuffer->Release();
1530 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1531 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1535 if (fragstring && fragstring[0])
1539 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1540 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1541 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1542 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1545 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1548 psbinsize = psbuffer->GetBufferSize();
1549 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1550 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1551 psbuffer->Release();
1555 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1556 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1560 Sys_UnloadLibrary(&d3dx9_dll);
1563 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1567 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1568 if (FAILED(vsresult))
1569 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1570 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1571 if (FAILED(psresult))
1572 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1574 // free the shader data
1575 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1576 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1579 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1582 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1583 int vertstring_length = 0;
1584 int geomstring_length = 0;
1585 int fragstring_length = 0;
1587 char *vertexstring, *geometrystring, *fragmentstring;
1588 char *vertstring, *geomstring, *fragstring;
1589 char permutationname[256];
1590 char cachename[256];
1591 int vertstrings_count = 0;
1592 int geomstrings_count = 0;
1593 int fragstrings_count = 0;
1594 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 p->vertexshader = NULL;
1602 p->pixelshader = NULL;
1604 permutationname[0] = 0;
1606 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1607 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1608 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1610 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1611 strlcat(cachename, "hlsl/", sizeof(cachename));
1613 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1614 vertstrings_count = 0;
1615 geomstrings_count = 0;
1616 fragstrings_count = 0;
1617 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1618 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1619 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1621 // the first pretext is which type of shader to compile as
1622 // (later these will all be bound together as a program object)
1623 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1624 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1625 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1627 // the second pretext is the mode (for example a light source)
1628 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1629 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1630 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1631 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1632 strlcat(cachename, modeinfo->name, sizeof(cachename));
1634 // now add all the permutation pretexts
1635 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1637 if (permutation & (1<<i))
1639 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1640 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1641 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1642 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1643 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1647 // keep line numbers correct
1648 vertstrings_list[vertstrings_count++] = "\n";
1649 geomstrings_list[geomstrings_count++] = "\n";
1650 fragstrings_list[fragstrings_count++] = "\n";
1655 R_CompileShader_AddStaticParms(mode, permutation);
1656 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657 vertstrings_count += shaderstaticparms_count;
1658 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659 geomstrings_count += shaderstaticparms_count;
1660 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661 fragstrings_count += shaderstaticparms_count;
1663 // replace spaces in the cachename with _ characters
1664 for (i = 0;cachename[i];i++)
1665 if (cachename[i] == ' ')
1668 // now append the shader text itself
1669 vertstrings_list[vertstrings_count++] = vertexstring;
1670 geomstrings_list[geomstrings_count++] = geometrystring;
1671 fragstrings_list[fragstrings_count++] = fragmentstring;
1673 // if any sources were NULL, clear the respective list
1675 vertstrings_count = 0;
1676 if (!geometrystring)
1677 geomstrings_count = 0;
1678 if (!fragmentstring)
1679 fragstrings_count = 0;
1681 vertstring_length = 0;
1682 for (i = 0;i < vertstrings_count;i++)
1683 vertstring_length += strlen(vertstrings_list[i]);
1684 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1685 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1686 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1688 geomstring_length = 0;
1689 for (i = 0;i < geomstrings_count;i++)
1690 geomstring_length += strlen(geomstrings_list[i]);
1691 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1692 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1693 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1695 fragstring_length = 0;
1696 for (i = 0;i < fragstrings_count;i++)
1697 fragstring_length += strlen(fragstrings_list[i]);
1698 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1699 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1700 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1702 // try to load the cached shader, or generate one
1703 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1705 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1706 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1708 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1712 Mem_Free(vertstring);
1714 Mem_Free(geomstring);
1716 Mem_Free(fragstring);
1718 Mem_Free(vertexstring);
1720 Mem_Free(geometrystring);
1722 Mem_Free(fragmentstring);
1725 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1726 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1727 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);}
1728 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);}
1729 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);}
1730 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);}
1732 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1739 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1741 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1742 if (r_hlsl_permutation != perm)
1744 r_hlsl_permutation = perm;
1745 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747 if (!r_hlsl_permutation->compiled)
1748 R_HLSL_CompilePermutation(perm, mode, permutation);
1749 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1751 // remove features until we find a valid permutation
1753 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1755 // reduce i more quickly whenever it would not remove any bits
1756 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1757 if (!(permutation & j))
1760 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1761 if (!r_hlsl_permutation->compiled)
1762 R_HLSL_CompilePermutation(perm, mode, permutation);
1763 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1766 if (i >= SHADERPERMUTATION_COUNT)
1768 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1769 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770 return; // no bit left to clear, entire mode is broken
1774 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1775 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1777 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1778 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1779 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1783 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1785 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1786 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1787 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1788 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1791 void R_GLSL_Restart_f(void)
1793 unsigned int i, limit;
1794 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1795 Mem_Free(glslshaderstring);
1796 glslshaderstring = NULL;
1797 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1798 Mem_Free(hlslshaderstring);
1799 hlslshaderstring = NULL;
1800 switch(vid.renderpath)
1802 case RENDERPATH_D3D9:
1805 r_hlsl_permutation_t *p;
1806 r_hlsl_permutation = NULL;
1807 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1808 for (i = 0;i < limit;i++)
1810 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1812 if (p->vertexshader)
1813 IDirect3DVertexShader9_Release(p->vertexshader);
1815 IDirect3DPixelShader9_Release(p->pixelshader);
1816 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1819 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1823 case RENDERPATH_D3D10:
1824 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826 case RENDERPATH_D3D11:
1827 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1829 case RENDERPATH_GL20:
1830 case RENDERPATH_GLES2:
1832 r_glsl_permutation_t *p;
1833 r_glsl_permutation = NULL;
1834 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1835 for (i = 0;i < limit;i++)
1837 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1839 GL_Backend_FreeProgram(p->program);
1840 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1843 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1846 case RENDERPATH_GL13:
1847 case RENDERPATH_GL11:
1849 case RENDERPATH_SOFT:
1854 void R_GLSL_DumpShader_f(void)
1859 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1862 FS_Print(file, "/* The engine may define the following macros:\n");
1863 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1864 for (i = 0;i < SHADERMODE_COUNT;i++)
1865 FS_Print(file, glslshadermodeinfo[i].pretext);
1866 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1867 FS_Print(file, shaderpermutationinfo[i].pretext);
1868 FS_Print(file, "*/\n");
1869 FS_Print(file, builtinshaderstring);
1871 Con_Printf("glsl/default.glsl written\n");
1874 Con_Printf("failed to write to glsl/default.glsl\n");
1876 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1879 FS_Print(file, "/* The engine may define the following macros:\n");
1880 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1881 for (i = 0;i < SHADERMODE_COUNT;i++)
1882 FS_Print(file, hlslshadermodeinfo[i].pretext);
1883 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884 FS_Print(file, shaderpermutationinfo[i].pretext);
1885 FS_Print(file, "*/\n");
1886 FS_Print(file, builtinhlslshaderstring);
1888 Con_Printf("hlsl/default.hlsl written\n");
1891 Con_Printf("failed to write to hlsl/default.hlsl\n");
1894 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1897 texturemode = GL_MODULATE;
1898 switch (vid.renderpath)
1900 case RENDERPATH_D3D9:
1902 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))));
1903 R_Mesh_TexBind(GL20TU_FIRST , first );
1904 R_Mesh_TexBind(GL20TU_SECOND, second);
1907 case RENDERPATH_D3D10:
1908 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1910 case RENDERPATH_D3D11:
1911 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1913 case RENDERPATH_GL20:
1914 case RENDERPATH_GLES2:
1915 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))));
1916 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1917 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1919 case RENDERPATH_GL13:
1920 R_Mesh_TexBind(0, first );
1921 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1922 R_Mesh_TexBind(1, second);
1924 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1926 case RENDERPATH_GL11:
1927 R_Mesh_TexBind(0, first );
1929 case RENDERPATH_SOFT:
1930 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))));
1931 R_Mesh_TexBind(GL20TU_FIRST , first );
1932 R_Mesh_TexBind(GL20TU_SECOND, second);
1937 void R_SetupShader_DepthOrShadow(void)
1939 switch (vid.renderpath)
1941 case RENDERPATH_D3D9:
1943 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1946 case RENDERPATH_D3D10:
1947 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949 case RENDERPATH_D3D11:
1950 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952 case RENDERPATH_GL20:
1953 case RENDERPATH_GLES2:
1954 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1956 case RENDERPATH_GL13:
1957 R_Mesh_TexBind(0, 0);
1958 R_Mesh_TexBind(1, 0);
1960 case RENDERPATH_GL11:
1961 R_Mesh_TexBind(0, 0);
1963 case RENDERPATH_SOFT:
1964 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1969 void R_SetupShader_ShowDepth(void)
1971 switch (vid.renderpath)
1973 case RENDERPATH_D3D9:
1975 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1978 case RENDERPATH_D3D10:
1979 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1981 case RENDERPATH_D3D11:
1982 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1984 case RENDERPATH_GL20:
1985 case RENDERPATH_GLES2:
1986 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1988 case RENDERPATH_GL13:
1990 case RENDERPATH_GL11:
1992 case RENDERPATH_SOFT:
1993 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1998 extern qboolean r_shadow_usingdeferredprepass;
1999 extern cvar_t r_shadow_deferred_8bitrange;
2000 extern rtexture_t *r_shadow_attenuationgradienttexture;
2001 extern rtexture_t *r_shadow_attenuation2dtexture;
2002 extern rtexture_t *r_shadow_attenuation3dtexture;
2003 extern qboolean r_shadow_usingshadowmap2d;
2004 extern qboolean r_shadow_usingshadowmaportho;
2005 extern float r_shadow_shadowmap_texturescale[2];
2006 extern float r_shadow_shadowmap_parameters[4];
2007 extern qboolean r_shadow_shadowmapvsdct;
2008 extern qboolean r_shadow_shadowmapsampler;
2009 extern int r_shadow_shadowmappcf;
2010 extern rtexture_t *r_shadow_shadowmap2dtexture;
2011 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2012 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2013 extern matrix4x4_t r_shadow_shadowmapmatrix;
2014 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2015 extern int r_shadow_prepass_width;
2016 extern int r_shadow_prepass_height;
2017 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2018 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2019 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2020 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2021 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2023 #define BLENDFUNC_ALLOWS_COLORMOD 1
2024 #define BLENDFUNC_ALLOWS_FOG 2
2025 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2026 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2027 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2028 static int R_BlendFuncFlags(int src, int dst)
2032 // a blendfunc allows colormod if:
2033 // a) it can never keep the destination pixel invariant, or
2034 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2035 // this is to prevent unintended side effects from colormod
2037 // a blendfunc allows fog if:
2038 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2039 // this is to prevent unintended side effects from fog
2041 // these checks are the output of fogeval.pl
2043 r |= BLENDFUNC_ALLOWS_COLORMOD;
2044 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2045 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2046 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2047 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2048 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2052 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2053 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2054 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2055 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2057 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2059 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2064 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069 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)
2071 // select a permutation of the lighting shader appropriate to this
2072 // combination of texture, entity, light source, and fogging, only use the
2073 // minimum features necessary to avoid wasting rendering time in the
2074 // fragment shader on features that are not being used
2075 unsigned int permutation = 0;
2076 unsigned int mode = 0;
2078 static float dummy_colormod[3] = {1, 1, 1};
2079 float *colormod = rsurface.colormod;
2081 matrix4x4_t tempmatrix;
2082 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2083 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2084 permutation |= SHADERPERMUTATION_ALPHAKILL;
2085 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2086 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2087 if (rsurfacepass == RSURFPASS_BACKGROUND)
2089 // distorted background
2090 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2092 mode = SHADERMODE_WATER;
2093 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2095 // this is the right thing to do for wateralpha
2096 GL_BlendFunc(GL_ONE, GL_ZERO);
2097 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2101 // this is the right thing to do for entity alpha
2102 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2103 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2106 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2108 mode = SHADERMODE_REFRACTION;
2109 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114 mode = SHADERMODE_GENERIC;
2115 permutation |= SHADERPERMUTATION_DIFFUSE;
2116 GL_BlendFunc(GL_ONE, GL_ZERO);
2117 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2120 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2122 if (r_glsl_offsetmapping.integer)
2124 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2125 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2126 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2127 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2128 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2130 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2131 if (r_glsl_offsetmapping_reliefmapping.integer)
2132 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2135 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2136 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2137 // normalmap (deferred prepass), may use alpha test on diffuse
2138 mode = SHADERMODE_DEFERREDGEOMETRY;
2139 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2140 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2141 GL_BlendFunc(GL_ONE, GL_ZERO);
2142 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2144 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2146 if (r_glsl_offsetmapping.integer)
2148 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2149 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2150 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2151 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2152 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2154 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2155 if (r_glsl_offsetmapping_reliefmapping.integer)
2156 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2159 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2160 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2162 mode = SHADERMODE_LIGHTSOURCE;
2163 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2164 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2165 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2166 permutation |= SHADERPERMUTATION_CUBEFILTER;
2167 if (diffusescale > 0)
2168 permutation |= SHADERPERMUTATION_DIFFUSE;
2169 if (specularscale > 0)
2170 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2171 if (r_refdef.fogenabled)
2172 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2173 if (rsurface.texture->colormapping)
2174 permutation |= SHADERPERMUTATION_COLORMAPPING;
2175 if (r_shadow_usingshadowmap2d)
2177 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2178 if(r_shadow_shadowmapvsdct)
2179 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2181 if (r_shadow_shadowmapsampler)
2182 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2183 if (r_shadow_shadowmappcf > 1)
2184 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2185 else if (r_shadow_shadowmappcf)
2186 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2188 if (rsurface.texture->reflectmasktexture)
2189 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2193 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2195 if (r_glsl_offsetmapping.integer)
2197 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2198 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2199 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2200 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2201 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2203 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2204 if (r_glsl_offsetmapping_reliefmapping.integer)
2205 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2208 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2209 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2210 // unshaded geometry (fullbright or ambient model lighting)
2211 mode = SHADERMODE_FLATCOLOR;
2212 ambientscale = diffusescale = specularscale = 0;
2213 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2214 permutation |= SHADERPERMUTATION_GLOW;
2215 if (r_refdef.fogenabled)
2216 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2217 if (rsurface.texture->colormapping)
2218 permutation |= SHADERPERMUTATION_COLORMAPPING;
2219 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2221 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2222 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2224 if (r_shadow_shadowmapsampler)
2225 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2226 if (r_shadow_shadowmappcf > 1)
2227 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2228 else if (r_shadow_shadowmappcf)
2229 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2232 permutation |= SHADERPERMUTATION_REFLECTION;
2233 if (rsurface.texture->reflectmasktexture)
2234 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2236 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2238 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2240 if (r_glsl_offsetmapping.integer)
2242 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2243 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2244 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2245 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2246 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2248 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2249 if (r_glsl_offsetmapping_reliefmapping.integer)
2250 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2253 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2254 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2255 // directional model lighting
2256 mode = SHADERMODE_LIGHTDIRECTION;
2257 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 permutation |= SHADERPERMUTATION_DIFFUSE;
2260 if (specularscale > 0)
2261 permutation |= SHADERPERMUTATION_SPECULAR;
2262 if (r_refdef.fogenabled)
2263 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2264 if (rsurface.texture->colormapping)
2265 permutation |= SHADERPERMUTATION_COLORMAPPING;
2266 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2268 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2269 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2271 if (r_shadow_shadowmapsampler)
2272 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2273 if (r_shadow_shadowmappcf > 1)
2274 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2275 else if (r_shadow_shadowmappcf)
2276 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2278 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2279 permutation |= SHADERPERMUTATION_REFLECTION;
2280 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2281 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2282 if (rsurface.texture->reflectmasktexture)
2283 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284 if (r_shadow_bouncegridtexture)
2286 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2287 if (r_shadow_bouncegriddirectional)
2288 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2290 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2295 if (r_glsl_offsetmapping.integer)
2297 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2298 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2299 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2300 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2301 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2303 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2304 if (r_glsl_offsetmapping_reliefmapping.integer)
2305 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2308 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2309 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2310 // ambient model lighting
2311 mode = SHADERMODE_LIGHTDIRECTION;
2312 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2313 permutation |= SHADERPERMUTATION_GLOW;
2314 if (r_refdef.fogenabled)
2315 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2316 if (rsurface.texture->colormapping)
2317 permutation |= SHADERPERMUTATION_COLORMAPPING;
2318 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2320 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2321 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2323 if (r_shadow_shadowmapsampler)
2324 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2325 if (r_shadow_shadowmappcf > 1)
2326 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2327 else if (r_shadow_shadowmappcf)
2328 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2330 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2331 permutation |= SHADERPERMUTATION_REFLECTION;
2332 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2333 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2334 if (rsurface.texture->reflectmasktexture)
2335 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336 if (r_shadow_bouncegridtexture)
2338 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2339 if (r_shadow_bouncegriddirectional)
2340 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2342 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2347 if (r_glsl_offsetmapping.integer)
2349 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2350 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2351 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2352 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2353 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2355 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2356 if (r_glsl_offsetmapping_reliefmapping.integer)
2357 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2360 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2363 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2364 permutation |= SHADERPERMUTATION_GLOW;
2365 if (r_refdef.fogenabled)
2366 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367 if (rsurface.texture->colormapping)
2368 permutation |= SHADERPERMUTATION_COLORMAPPING;
2369 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2371 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2374 if (r_shadow_shadowmapsampler)
2375 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2376 if (r_shadow_shadowmappcf > 1)
2377 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2378 else if (r_shadow_shadowmappcf)
2379 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2381 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2382 permutation |= SHADERPERMUTATION_REFLECTION;
2383 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2384 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2385 if (rsurface.texture->reflectmasktexture)
2386 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2387 if (FAKELIGHT_ENABLED)
2389 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2390 mode = SHADERMODE_FAKELIGHT;
2391 permutation |= SHADERPERMUTATION_DIFFUSE;
2392 if (specularscale > 0)
2393 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2397 // deluxemapping (light direction texture)
2398 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2399 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2401 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2402 permutation |= SHADERPERMUTATION_DIFFUSE;
2403 if (specularscale > 0)
2404 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2406 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2408 // fake deluxemapping (uniform light direction in tangentspace)
2409 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2410 permutation |= SHADERPERMUTATION_DIFFUSE;
2411 if (specularscale > 0)
2412 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2414 else if (rsurface.uselightmaptexture)
2416 // ordinary lightmapping (q1bsp, q3bsp)
2417 mode = SHADERMODE_LIGHTMAP;
2421 // ordinary vertex coloring (q3bsp)
2422 mode = SHADERMODE_VERTEXCOLOR;
2424 if (r_shadow_bouncegridtexture)
2426 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2427 if (r_shadow_bouncegriddirectional)
2428 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2430 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2433 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2434 colormod = dummy_colormod;
2435 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2436 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2437 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2438 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2439 switch(vid.renderpath)
2441 case RENDERPATH_D3D9:
2443 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);
2444 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2445 R_SetupShader_SetPermutationHLSL(mode, permutation);
2446 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2447 if (mode == SHADERMODE_LIGHTSOURCE)
2449 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2450 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2454 if (mode == SHADERMODE_LIGHTDIRECTION)
2456 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2459 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2460 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2461 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2462 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2463 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2465 if (mode == SHADERMODE_LIGHTSOURCE)
2467 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2468 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2469 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2470 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2471 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2473 // additive passes are only darkened by fog, not tinted
2474 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2475 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2479 if (mode == SHADERMODE_FLATCOLOR)
2481 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2483 else if (mode == SHADERMODE_LIGHTDIRECTION)
2485 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]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2487 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2488 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2489 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2491 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2495 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2496 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2497 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);
2498 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);
2499 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2501 // additive passes are only darkened by fog, not tinted
2502 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2503 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2505 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2506 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);
2507 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2508 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2509 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2510 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2511 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2512 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2513 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2514 if (mode == SHADERMODE_WATER)
2515 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2517 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2518 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2520 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));
2521 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2522 if (rsurface.texture->pantstexture)
2523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2526 if (rsurface.texture->shirttexture)
2527 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2529 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2530 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2532 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2533 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2534 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2535 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2536 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2538 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2539 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2540 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2541 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2542 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2543 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2544 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2545 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2546 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2547 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2548 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2549 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2550 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2551 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2552 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2553 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2554 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2555 if (rsurfacepass == RSURFPASS_BACKGROUND)
2557 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2558 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2559 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2563 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2565 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2566 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2567 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2568 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2569 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2571 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2572 if (rsurface.rtlight)
2574 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2575 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2580 case RENDERPATH_D3D10:
2581 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2583 case RENDERPATH_D3D11:
2584 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2586 case RENDERPATH_GL20:
2587 case RENDERPATH_GLES2:
2588 if (!vid.useinterleavedarrays)
2590 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);
2591 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2592 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2593 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2594 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2595 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2596 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2597 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2601 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);
2602 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2604 R_SetupShader_SetPermutationGLSL(mode, permutation);
2605 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2606 if (mode == SHADERMODE_LIGHTSOURCE)
2608 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2609 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2611 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2612 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2613 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);
2615 // additive passes are only darkened by fog, not tinted
2616 if (r_glsl_permutation->loc_FogColor >= 0)
2617 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2618 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2622 if (mode == SHADERMODE_FLATCOLOR)
2624 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2626 else if (mode == SHADERMODE_LIGHTDIRECTION)
2628 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]);
2629 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]);
2630 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2631 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2632 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2633 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]);
2634 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]);
2638 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]);
2639 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]);
2640 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);
2641 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);
2642 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);
2644 // additive passes are only darkened by fog, not tinted
2645 if (r_glsl_permutation->loc_FogColor >= 0)
2647 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2648 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2650 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2652 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);
2653 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]);
2654 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]);
2655 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]);
2656 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]);
2657 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2658 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2659 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2660 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]);
2662 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2663 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2664 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2665 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]);
2666 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]);
2668 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2669 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));
2670 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2671 if (r_glsl_permutation->loc_Color_Pants >= 0)
2673 if (rsurface.texture->pantstexture)
2674 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2676 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2678 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2680 if (rsurface.texture->shirttexture)
2681 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2683 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2685 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]);
2686 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2687 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2688 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2689 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2690 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]);
2691 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2692 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);}
2693 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2695 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2696 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2697 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2698 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2699 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2700 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2701 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2703 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2704 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2705 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2706 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2707 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2708 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2709 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);
2710 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2711 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2712 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2715 if (rsurfacepass == RSURFPASS_BACKGROUND)
2717 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);
2718 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);
2719 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);
2723 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);
2725 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2726 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2727 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2728 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2729 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2731 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2732 if (rsurface.rtlight)
2734 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2735 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2738 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2741 case RENDERPATH_GL13:
2742 case RENDERPATH_GL11:
2744 case RENDERPATH_SOFT:
2745 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);
2746 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747 R_SetupShader_SetPermutationSoft(mode, permutation);
2748 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749 if (mode == SHADERMODE_LIGHTSOURCE)
2751 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2758 // additive passes are only darkened by fog, not tinted
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2764 if (mode == SHADERMODE_FLATCOLOR)
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2768 else if (mode == SHADERMODE_LIGHTDIRECTION)
2770 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]);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775 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]);
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782 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);
2783 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);
2784 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2786 // additive passes are only darkened by fog, not tinted
2787 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791 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);
2792 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794 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]);
2795 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]);
2796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2801 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805 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]);
2807 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808 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));
2809 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2812 if (rsurface.texture->pantstexture)
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2815 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2817 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2819 if (rsurface.texture->shirttexture)
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2824 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2829 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2830 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2832 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2833 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2834 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2835 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2836 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2837 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2838 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2839 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2840 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2841 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2842 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2843 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2844 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2845 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2846 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2847 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2848 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2849 if (rsurfacepass == RSURFPASS_BACKGROUND)
2851 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2852 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2853 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2857 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2859 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2860 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2861 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2862 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2863 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2865 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2866 if (rsurface.rtlight)
2868 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2869 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2876 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2878 // select a permutation of the lighting shader appropriate to this
2879 // combination of texture, entity, light source, and fogging, only use the
2880 // minimum features necessary to avoid wasting rendering time in the
2881 // fragment shader on features that are not being used
2882 unsigned int permutation = 0;
2883 unsigned int mode = 0;
2884 const float *lightcolorbase = rtlight->currentcolor;
2885 float ambientscale = rtlight->ambientscale;
2886 float diffusescale = rtlight->diffusescale;
2887 float specularscale = rtlight->specularscale;
2888 // this is the location of the light in view space
2889 vec3_t viewlightorigin;
2890 // this transforms from view space (camera) to light space (cubemap)
2891 matrix4x4_t viewtolight;
2892 matrix4x4_t lighttoview;
2893 float viewtolight16f[16];
2894 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2896 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2897 if (rtlight->currentcubemap != r_texture_whitecube)
2898 permutation |= SHADERPERMUTATION_CUBEFILTER;
2899 if (diffusescale > 0)
2900 permutation |= SHADERPERMUTATION_DIFFUSE;
2901 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2902 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2903 if (r_shadow_usingshadowmap2d)
2905 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2906 if (r_shadow_shadowmapvsdct)
2907 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2909 if (r_shadow_shadowmapsampler)
2910 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2911 if (r_shadow_shadowmappcf > 1)
2912 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2913 else if (r_shadow_shadowmappcf)
2914 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2916 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2917 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2918 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2919 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2920 switch(vid.renderpath)
2922 case RENDERPATH_D3D9:
2924 R_SetupShader_SetPermutationHLSL(mode, permutation);
2925 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2926 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2927 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2928 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2929 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2930 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2931 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2932 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2933 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2934 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2936 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2937 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2938 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2939 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2940 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2941 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2944 case RENDERPATH_D3D10:
2945 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2947 case RENDERPATH_D3D11:
2948 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2950 case RENDERPATH_GL20:
2951 case RENDERPATH_GLES2:
2952 R_SetupShader_SetPermutationGLSL(mode, permutation);
2953 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2954 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2955 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);
2956 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);
2957 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);
2958 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]);
2959 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]);
2960 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));
2961 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]);
2962 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2964 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2965 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2966 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2967 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2968 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2969 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2971 case RENDERPATH_GL13:
2972 case RENDERPATH_GL11:
2974 case RENDERPATH_SOFT:
2975 R_SetupShader_SetPermutationGLSL(mode, permutation);
2976 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2977 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2978 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2979 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2980 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2981 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2982 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]);
2983 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));
2984 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2985 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2987 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2988 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2989 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2990 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2991 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2992 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2997 #define SKINFRAME_HASH 1024
3001 int loadsequence; // incremented each level change
3002 memexpandablearray_t array;
3003 skinframe_t *hash[SKINFRAME_HASH];
3006 r_skinframe_t r_skinframe;
3008 void R_SkinFrame_PrepareForPurge(void)
3010 r_skinframe.loadsequence++;
3011 // wrap it without hitting zero
3012 if (r_skinframe.loadsequence >= 200)
3013 r_skinframe.loadsequence = 1;
3016 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3020 // mark the skinframe as used for the purging code
3021 skinframe->loadsequence = r_skinframe.loadsequence;
3024 void R_SkinFrame_Purge(void)
3028 for (i = 0;i < SKINFRAME_HASH;i++)
3030 for (s = r_skinframe.hash[i];s;s = s->next)
3032 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3034 if (s->merged == s->base)
3036 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3037 R_PurgeTexture(s->stain );s->stain = NULL;
3038 R_PurgeTexture(s->merged);s->merged = NULL;
3039 R_PurgeTexture(s->base );s->base = NULL;
3040 R_PurgeTexture(s->pants );s->pants = NULL;
3041 R_PurgeTexture(s->shirt );s->shirt = NULL;
3042 R_PurgeTexture(s->nmap );s->nmap = NULL;
3043 R_PurgeTexture(s->gloss );s->gloss = NULL;
3044 R_PurgeTexture(s->glow );s->glow = NULL;
3045 R_PurgeTexture(s->fog );s->fog = NULL;
3046 R_PurgeTexture(s->reflect);s->reflect = NULL;
3047 s->loadsequence = 0;
3053 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3055 char basename[MAX_QPATH];
3057 Image_StripImageExtension(name, basename, sizeof(basename));
3059 if( last == NULL ) {
3061 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3062 item = r_skinframe.hash[hashindex];
3067 // linearly search through the hash bucket
3068 for( ; item ; item = item->next ) {
3069 if( !strcmp( item->basename, basename ) ) {
3076 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3080 char basename[MAX_QPATH];
3082 Image_StripImageExtension(name, basename, sizeof(basename));
3084 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3085 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3086 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3090 rtexture_t *dyntexture;
3091 // check whether its a dynamic texture
3092 dyntexture = CL_GetDynTexture( basename );
3093 if (!add && !dyntexture)
3095 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3096 memset(item, 0, sizeof(*item));
3097 strlcpy(item->basename, basename, sizeof(item->basename));
3098 item->base = dyntexture; // either NULL or dyntexture handle
3099 item->textureflags = textureflags;
3100 item->comparewidth = comparewidth;
3101 item->compareheight = compareheight;
3102 item->comparecrc = comparecrc;
3103 item->next = r_skinframe.hash[hashindex];
3104 r_skinframe.hash[hashindex] = item;
3106 else if( item->base == NULL )
3108 rtexture_t *dyntexture;
3109 // check whether its a dynamic texture
3110 // 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]
3111 dyntexture = CL_GetDynTexture( basename );
3112 item->base = dyntexture; // either NULL or dyntexture handle
3115 R_SkinFrame_MarkUsed(item);
3119 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3121 unsigned long long avgcolor[5], wsum; \
3129 for(pix = 0; pix < cnt; ++pix) \
3132 for(comp = 0; comp < 3; ++comp) \
3134 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3137 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3139 for(comp = 0; comp < 3; ++comp) \
3140 avgcolor[comp] += getpixel * w; \
3143 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144 avgcolor[4] += getpixel; \
3146 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3148 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3149 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3150 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3151 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3154 extern cvar_t gl_picmip;
3155 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3158 unsigned char *pixels;
3159 unsigned char *bumppixels;
3160 unsigned char *basepixels = NULL;
3161 int basepixels_width = 0;
3162 int basepixels_height = 0;
3163 skinframe_t *skinframe;
3164 rtexture_t *ddsbase = NULL;
3165 qboolean ddshasalpha = false;
3166 float ddsavgcolor[4];
3167 char basename[MAX_QPATH];
3168 int miplevel = R_PicmipForFlags(textureflags);
3169 int savemiplevel = miplevel;
3172 if (cls.state == ca_dedicated)
3175 // return an existing skinframe if already loaded
3176 // if loading of the first image fails, don't make a new skinframe as it
3177 // would cause all future lookups of this to be missing
3178 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3179 if (skinframe && skinframe->base)
3182 Image_StripImageExtension(name, basename, sizeof(basename));
3184 // check for DDS texture file first
3185 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3187 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3188 if (basepixels == NULL)
3192 // FIXME handle miplevel
3194 if (developer_loading.integer)
3195 Con_Printf("loading skin \"%s\"\n", name);
3197 // we've got some pixels to store, so really allocate this new texture now
3199 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3200 skinframe->stain = NULL;
3201 skinframe->merged = NULL;
3202 skinframe->base = NULL;
3203 skinframe->pants = NULL;
3204 skinframe->shirt = NULL;
3205 skinframe->nmap = NULL;
3206 skinframe->gloss = NULL;
3207 skinframe->glow = NULL;
3208 skinframe->fog = NULL;
3209 skinframe->reflect = NULL;
3210 skinframe->hasalpha = false;
3214 skinframe->base = ddsbase;
3215 skinframe->hasalpha = ddshasalpha;
3216 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3217 if (r_loadfog && skinframe->hasalpha)
3218 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3219 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3223 basepixels_width = image_width;
3224 basepixels_height = image_height;
3225 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3226 if (textureflags & TEXF_ALPHA)
3228 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3230 if (basepixels[j] < 255)
3232 skinframe->hasalpha = true;
3236 if (r_loadfog && skinframe->hasalpha)
3238 // has transparent pixels
3239 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3240 for (j = 0;j < image_width * image_height * 4;j += 4)
3245 pixels[j+3] = basepixels[j+3];
3247 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);
3251 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3252 //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]);
3253 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3254 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3255 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3256 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3261 mymiplevel = savemiplevel;
3262 if (r_loadnormalmap)
3263 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);
3264 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3266 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 // _norm is the name used by tenebrae and has been adopted as standard
3273 if (r_loadnormalmap && skinframe->nmap == NULL)
3275 mymiplevel = savemiplevel;
3276 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3278 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);
3282 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3284 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3285 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3286 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);
3288 Mem_Free(bumppixels);
3290 else if (r_shadow_bumpscale_basetexture.value > 0)
3292 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3293 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3294 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);
3297 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3298 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3301 // _luma is supported only for tenebrae compatibility
3302 // _glow is the preferred name
3303 mymiplevel = savemiplevel;
3304 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3306 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3307 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3308 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3309 Mem_Free(pixels);pixels = NULL;
3312 mymiplevel = savemiplevel;
3313 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3315 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3316 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3317 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3322 mymiplevel = savemiplevel;
3323 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3325 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3326 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3327 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3332 mymiplevel = savemiplevel;
3333 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3335 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3336 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3337 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3342 mymiplevel = savemiplevel;
3343 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3345 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3346 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3347 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3353 Mem_Free(basepixels);
3358 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3359 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3362 unsigned char *temp1, *temp2;
3363 skinframe_t *skinframe;
3365 if (cls.state == ca_dedicated)
3368 // if already loaded just return it, otherwise make a new skinframe
3369 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3370 if (skinframe && skinframe->base)
3373 skinframe->stain = NULL;
3374 skinframe->merged = NULL;
3375 skinframe->base = NULL;
3376 skinframe->pants = NULL;
3377 skinframe->shirt = NULL;
3378 skinframe->nmap = NULL;
3379 skinframe->gloss = NULL;
3380 skinframe->glow = NULL;
3381 skinframe->fog = NULL;
3382 skinframe->reflect = NULL;
3383 skinframe->hasalpha = false;
3385 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3389 if (developer_loading.integer)
3390 Con_Printf("loading 32bit skin \"%s\"\n", name);
3392 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3394 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3395 temp2 = temp1 + width * height * 4;
3396 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3397 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);
3400 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3401 if (textureflags & TEXF_ALPHA)
3403 for (i = 3;i < width * height * 4;i += 4)
3405 if (skindata[i] < 255)
3407 skinframe->hasalpha = true;
3411 if (r_loadfog && skinframe->hasalpha)
3413 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3414 memcpy(fogpixels, skindata, width * height * 4);
3415 for (i = 0;i < width * height * 4;i += 4)
3416 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3417 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3418 Mem_Free(fogpixels);
3422 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3423 //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]);
3428 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3432 skinframe_t *skinframe;
3434 if (cls.state == ca_dedicated)
3437 // if already loaded just return it, otherwise make a new skinframe
3438 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3439 if (skinframe && skinframe->base)
3442 skinframe->stain = NULL;
3443 skinframe->merged = NULL;
3444 skinframe->base = NULL;
3445 skinframe->pants = NULL;
3446 skinframe->shirt = NULL;
3447 skinframe->nmap = NULL;
3448 skinframe->gloss = NULL;
3449 skinframe->glow = NULL;
3450 skinframe->fog = NULL;
3451 skinframe->reflect = NULL;
3452 skinframe->hasalpha = false;
3454 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3458 if (developer_loading.integer)
3459 Con_Printf("loading quake skin \"%s\"\n", name);
3461 // 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)
3462 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3463 memcpy(skinframe->qpixels, skindata, width*height);
3464 skinframe->qwidth = width;
3465 skinframe->qheight = height;
3468 for (i = 0;i < width * height;i++)
3469 featuresmask |= palette_featureflags[skindata[i]];
3471 skinframe->hasalpha = false;
3472 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3473 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3474 skinframe->qgeneratemerged = true;
3475 skinframe->qgeneratebase = skinframe->qhascolormapping;
3476 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3478 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3479 //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]);
3484 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3488 unsigned char *skindata;
3490 if (!skinframe->qpixels)
3493 if (!skinframe->qhascolormapping)
3494 colormapped = false;
3498 if (!skinframe->qgeneratebase)
3503 if (!skinframe->qgeneratemerged)
3507 width = skinframe->qwidth;
3508 height = skinframe->qheight;
3509 skindata = skinframe->qpixels;
3511 if (skinframe->qgeneratenmap)
3513 unsigned char *temp1, *temp2;
3514 skinframe->qgeneratenmap = false;
3515 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3516 temp2 = temp1 + width * height * 4;
3517 // use either a custom palette or the quake palette
3518 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3519 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3520 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);
3524 if (skinframe->qgenerateglow)
3526 skinframe->qgenerateglow = false;
3527 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3532 skinframe->qgeneratebase = false;
3533 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);
3534 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3535 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3539 skinframe->qgeneratemerged = false;
3540 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);
3543 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3545 Mem_Free(skinframe->qpixels);
3546 skinframe->qpixels = NULL;
3550 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)
3553 skinframe_t *skinframe;
3555 if (cls.state == ca_dedicated)
3558 // if already loaded just return it, otherwise make a new skinframe
3559 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3560 if (skinframe && skinframe->base)
3563 skinframe->stain = NULL;
3564 skinframe->merged = NULL;
3565 skinframe->base = NULL;
3566 skinframe->pants = NULL;
3567 skinframe->shirt = NULL;
3568 skinframe->nmap = NULL;
3569 skinframe->gloss = NULL;
3570 skinframe->glow = NULL;
3571 skinframe->fog = NULL;
3572 skinframe->reflect = NULL;
3573 skinframe->hasalpha = false;
3575 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3579 if (developer_loading.integer)
3580 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3582 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3583 if (textureflags & TEXF_ALPHA)
3585 for (i = 0;i < width * height;i++)
3587 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3589 skinframe->hasalpha = true;
3593 if (r_loadfog && skinframe->hasalpha)
3594 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3597 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3598 //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]);
3603 skinframe_t *R_SkinFrame_LoadMissing(void)
3605 skinframe_t *skinframe;
3607 if (cls.state == ca_dedicated)
3610 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3611 skinframe->stain = NULL;
3612 skinframe->merged = NULL;
3613 skinframe->base = NULL;
3614 skinframe->pants = NULL;
3615 skinframe->shirt = NULL;
3616 skinframe->nmap = NULL;
3617 skinframe->gloss = NULL;
3618 skinframe->glow = NULL;
3619 skinframe->fog = NULL;
3620 skinframe->reflect = NULL;
3621 skinframe->hasalpha = false;
3623 skinframe->avgcolor[0] = rand() / RAND_MAX;
3624 skinframe->avgcolor[1] = rand() / RAND_MAX;
3625 skinframe->avgcolor[2] = rand() / RAND_MAX;
3626 skinframe->avgcolor[3] = 1;
3631 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3632 typedef struct suffixinfo_s
3635 qboolean flipx, flipy, flipdiagonal;
3638 static suffixinfo_t suffix[3][6] =
3641 {"px", false, false, false},
3642 {"nx", false, false, false},
3643 {"py", false, false, false},
3644 {"ny", false, false, false},
3645 {"pz", false, false, false},
3646 {"nz", false, false, false}
3649 {"posx", false, false, false},
3650 {"negx", false, false, false},
3651 {"posy", false, false, false},
3652 {"negy", false, false, false},
3653 {"posz", false, false, false},
3654 {"negz", false, false, false}
3657 {"rt", true, false, true},
3658 {"lf", false, true, true},
3659 {"ft", true, true, false},
3660 {"bk", false, false, false},
3661 {"up", true, false, true},
3662 {"dn", true, false, true}
3666 static int componentorder[4] = {0, 1, 2, 3};
3668 rtexture_t *R_LoadCubemap(const char *basename)
3670 int i, j, cubemapsize;
3671 unsigned char *cubemappixels, *image_buffer;
3672 rtexture_t *cubemaptexture;
3674 // must start 0 so the first loadimagepixels has no requested width/height
3676 cubemappixels = NULL;
3677 cubemaptexture = NULL;
3678 // keep trying different suffix groups (posx, px, rt) until one loads
3679 for (j = 0;j < 3 && !cubemappixels;j++)
3681 // load the 6 images in the suffix group
3682 for (i = 0;i < 6;i++)
3684 // generate an image name based on the base and and suffix
3685 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3687 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3689 // an image loaded, make sure width and height are equal
3690 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3692 // if this is the first image to load successfully, allocate the cubemap memory
3693 if (!cubemappixels && image_width >= 1)
3695 cubemapsize = image_width;
3696 // note this clears to black, so unavailable sides are black
3697 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3699 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3701 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);
3704 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3706 Mem_Free(image_buffer);
3710 // if a cubemap loaded, upload it
3713 if (developer_loading.integer)
3714 Con_Printf("loading cubemap \"%s\"\n", basename);
3716 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3717 Mem_Free(cubemappixels);
3721 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3722 if (developer_loading.integer)
3724 Con_Printf("(tried tried images ");
3725 for (j = 0;j < 3;j++)
3726 for (i = 0;i < 6;i++)
3727 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3728 Con_Print(" and was unable to find any of them).\n");
3731 return cubemaptexture;
3734 rtexture_t *R_GetCubemap(const char *basename)
3737 for (i = 0;i < r_texture_numcubemaps;i++)
3738 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3739 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3740 if (i >= MAX_CUBEMAPS)
3741 return r_texture_whitecube;
3742 r_texture_numcubemaps++;
3743 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3744 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3745 return r_texture_cubemaps[i].texture;
3748 void R_FreeCubemaps(void)
3751 for (i = 0;i < r_texture_numcubemaps;i++)
3753 if (developer_loading.integer)
3754 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3755 if (r_texture_cubemaps[i].texture)
3756 R_FreeTexture(r_texture_cubemaps[i].texture);
3758 r_texture_numcubemaps = 0;
3761 void R_Main_FreeViewCache(void)
3763 if (r_refdef.viewcache.entityvisible)
3764 Mem_Free(r_refdef.viewcache.entityvisible);
3765 if (r_refdef.viewcache.world_pvsbits)
3766 Mem_Free(r_refdef.viewcache.world_pvsbits);
3767 if (r_refdef.viewcache.world_leafvisible)
3768 Mem_Free(r_refdef.viewcache.world_leafvisible);
3769 if (r_refdef.viewcache.world_surfacevisible)
3770 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3771 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3774 void R_Main_ResizeViewCache(void)
3776 int numentities = r_refdef.scene.numentities;
3777 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3778 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3779 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3780 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3781 if (r_refdef.viewcache.maxentities < numentities)
3783 r_refdef.viewcache.maxentities = numentities;
3784 if (r_refdef.viewcache.entityvisible)
3785 Mem_Free(r_refdef.viewcache.entityvisible);
3786 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3788 if (r_refdef.viewcache.world_numclusters != numclusters)
3790 r_refdef.viewcache.world_numclusters = numclusters;
3791 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3792 if (r_refdef.viewcache.world_pvsbits)
3793 Mem_Free(r_refdef.viewcache.world_pvsbits);
3794 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3796 if (r_refdef.viewcache.world_numleafs != numleafs)
3798 r_refdef.viewcache.world_numleafs = numleafs;
3799 if (r_refdef.viewcache.world_leafvisible)
3800 Mem_Free(r_refdef.viewcache.world_leafvisible);
3801 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3803 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3805 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3806 if (r_refdef.viewcache.world_surfacevisible)
3807 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3808 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3812 extern rtexture_t *loadingscreentexture;
3813 void gl_main_start(void)
3815 loadingscreentexture = NULL;
3816 r_texture_blanknormalmap = NULL;
3817 r_texture_white = NULL;
3818 r_texture_grey128 = NULL;
3819 r_texture_black = NULL;
3820 r_texture_whitecube = NULL;
3821 r_texture_normalizationcube = NULL;
3822 r_texture_fogattenuation = NULL;
3823 r_texture_fogheighttexture = NULL;
3824 r_texture_gammaramps = NULL;
3825 r_texture_numcubemaps = 0;
3827 r_loaddds = r_texture_dds_load.integer != 0;
3828 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3830 switch(vid.renderpath)
3832 case RENDERPATH_GL20:
3833 case RENDERPATH_D3D9:
3834 case RENDERPATH_D3D10:
3835 case RENDERPATH_D3D11:
3836 case RENDERPATH_SOFT:
3837 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3838 Cvar_SetValueQuick(&gl_combine, 1);
3839 Cvar_SetValueQuick(&r_glsl, 1);
3840 r_loadnormalmap = true;
3844 case RENDERPATH_GL13:
3845 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3846 Cvar_SetValueQuick(&gl_combine, 1);
3847 Cvar_SetValueQuick(&r_glsl, 0);
3848 r_loadnormalmap = false;
3849 r_loadgloss = false;
3852 case RENDERPATH_GL11:
3853 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3854 Cvar_SetValueQuick(&gl_combine, 0);
3855 Cvar_SetValueQuick(&r_glsl, 0);
3856 r_loadnormalmap = false;
3857 r_loadgloss = false;
3860 case RENDERPATH_GLES2:
3861 Cvar_SetValueQuick(&r_textureunits, 1);
3862 Cvar_SetValueQuick(&gl_combine, 1);
3863 Cvar_SetValueQuick(&r_glsl, 1);
3864 r_loadnormalmap = true;
3865 r_loadgloss = false;
3871 R_FrameData_Reset();
3875 memset(r_queries, 0, sizeof(r_queries));
3877 r_qwskincache = NULL;
3878 r_qwskincache_size = 0;
3880 // due to caching of texture_t references, the collision cache must be reset
3881 Collision_Cache_Reset(true);
3883 // set up r_skinframe loading system for textures
3884 memset(&r_skinframe, 0, sizeof(r_skinframe));
3885 r_skinframe.loadsequence = 1;
3886 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3888 r_main_texturepool = R_AllocTexturePool();
3889 R_BuildBlankTextures();
3891 if (vid.support.arb_texture_cube_map)
3894 R_BuildNormalizationCube();
3896 r_texture_fogattenuation = NULL;
3897 r_texture_fogheighttexture = NULL;
3898 r_texture_gammaramps = NULL;
3899 //r_texture_fogintensity = NULL;
3900 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3901 memset(&r_waterstate, 0, sizeof(r_waterstate));
3902 r_glsl_permutation = NULL;
3903 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3904 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3905 glslshaderstring = NULL;
3907 r_hlsl_permutation = NULL;
3908 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3909 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3911 hlslshaderstring = NULL;
3912 memset(&r_svbsp, 0, sizeof (r_svbsp));
3914 r_refdef.fogmasktable_density = 0;
3917 void gl_main_shutdown(void)
3920 R_FrameData_Reset();
3922 R_Main_FreeViewCache();
3924 switch(vid.renderpath)
3926 case RENDERPATH_GL11:
3927 case RENDERPATH_GL13:
3928 case RENDERPATH_GL20:
3929 case RENDERPATH_GLES2:
3931 qglDeleteQueriesARB(r_maxqueries, r_queries);
3933 case RENDERPATH_D3D9:
3934 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3936 case RENDERPATH_D3D10:
3937 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3939 case RENDERPATH_D3D11:
3940 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942 case RENDERPATH_SOFT:
3948 memset(r_queries, 0, sizeof(r_queries));
3950 r_qwskincache = NULL;
3951 r_qwskincache_size = 0;
3953 // clear out the r_skinframe state
3954 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3955 memset(&r_skinframe, 0, sizeof(r_skinframe));
3958 Mem_Free(r_svbsp.nodes);
3959 memset(&r_svbsp, 0, sizeof (r_svbsp));
3960 R_FreeTexturePool(&r_main_texturepool);
3961 loadingscreentexture = NULL;
3962 r_texture_blanknormalmap = NULL;
3963 r_texture_white = NULL;
3964 r_texture_grey128 = NULL;
3965 r_texture_black = NULL;
3966 r_texture_whitecube = NULL;
3967 r_texture_normalizationcube = NULL;
3968 r_texture_fogattenuation = NULL;
3969 r_texture_fogheighttexture = NULL;
3970 r_texture_gammaramps = NULL;
3971 r_texture_numcubemaps = 0;
3972 //r_texture_fogintensity = NULL;
3973 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3974 memset(&r_waterstate, 0, sizeof(r_waterstate));
3977 r_glsl_permutation = NULL;
3978 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3979 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3980 glslshaderstring = NULL;
3982 r_hlsl_permutation = NULL;
3983 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3984 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3986 hlslshaderstring = NULL;
3989 extern void CL_ParseEntityLump(char *entitystring);
3990 void gl_main_newmap(void)
3992 // FIXME: move this code to client
3993 char *entities, entname[MAX_QPATH];
3995 Mem_Free(r_qwskincache);
3996 r_qwskincache = NULL;
3997 r_qwskincache_size = 0;
4000 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4001 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4003 CL_ParseEntityLump(entities);
4007 if (cl.worldmodel->brush.entities)
4008 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4010 R_Main_FreeViewCache();
4012 R_FrameData_Reset();
4015 void GL_Main_Init(void)
4017 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4019 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4020 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4021 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4022 if (gamemode == GAME_NEHAHRA)
4024 Cvar_RegisterVariable (&gl_fogenable);
4025 Cvar_RegisterVariable (&gl_fogdensity);
4026 Cvar_RegisterVariable (&gl_fogred);
4027 Cvar_RegisterVariable (&gl_foggreen);
4028 Cvar_RegisterVariable (&gl_fogblue);
4029 Cvar_RegisterVariable (&gl_fogstart);
4030 Cvar_RegisterVariable (&gl_fogend);
4031 Cvar_RegisterVariable (&gl_skyclip);
4033 Cvar_RegisterVariable(&r_motionblur);
4034 Cvar_RegisterVariable(&r_motionblur_maxblur);
4035 Cvar_RegisterVariable(&r_motionblur_bmin);
4036 Cvar_RegisterVariable(&r_motionblur_vmin);
4037 Cvar_RegisterVariable(&r_motionblur_vmax);
4038 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4039 Cvar_RegisterVariable(&r_motionblur_randomize);
4040 Cvar_RegisterVariable(&r_damageblur);
4041 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4042 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4043 Cvar_RegisterVariable(&r_equalize_entities_by);
4044 Cvar_RegisterVariable(&r_equalize_entities_to);
4045 Cvar_RegisterVariable(&r_depthfirst);
4046 Cvar_RegisterVariable(&r_useinfinitefarclip);
4047 Cvar_RegisterVariable(&r_farclip_base);
4048 Cvar_RegisterVariable(&r_farclip_world);
4049 Cvar_RegisterVariable(&r_nearclip);
4050 Cvar_RegisterVariable(&r_showbboxes);
4051 Cvar_RegisterVariable(&r_showsurfaces);
4052 Cvar_RegisterVariable(&r_showtris);
4053 Cvar_RegisterVariable(&r_shownormals);
4054 Cvar_RegisterVariable(&r_showlighting);
4055 Cvar_RegisterVariable(&r_showshadowvolumes);
4056 Cvar_RegisterVariable(&r_showcollisionbrushes);
4057 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4058 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4059 Cvar_RegisterVariable(&r_showdisabledepthtest);
4060 Cvar_RegisterVariable(&r_drawportals);
4061 Cvar_RegisterVariable(&r_drawentities);
4062 Cvar_RegisterVariable(&r_draw2d);
4063 Cvar_RegisterVariable(&r_drawworld);
4064 Cvar_RegisterVariable(&r_cullentities_trace);
4065 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4066 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4067 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4068 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4069 Cvar_RegisterVariable(&r_drawviewmodel);
4070 Cvar_RegisterVariable(&r_drawexteriormodel);
4071 Cvar_RegisterVariable(&r_speeds);
4072 Cvar_RegisterVariable(&r_fullbrights);
4073 Cvar_RegisterVariable(&r_wateralpha);
4074 Cvar_RegisterVariable(&r_dynamic);
4075 Cvar_RegisterVariable(&r_fakelight);
4076 Cvar_RegisterVariable(&r_fakelight_intensity);
4077 Cvar_RegisterVariable(&r_fullbright);
4078 Cvar_RegisterVariable(&r_shadows);
4079 Cvar_RegisterVariable(&r_shadows_darken);
4080 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4081 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4082 Cvar_RegisterVariable(&r_shadows_throwdistance);
4083 Cvar_RegisterVariable(&r_shadows_throwdirection);
4084 Cvar_RegisterVariable(&r_shadows_focus);
4085 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4086 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4087 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4088 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4089 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4090 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4091 Cvar_RegisterVariable(&r_fog_exp2);
4092 Cvar_RegisterVariable(&r_fog_clear);
4093 Cvar_RegisterVariable(&r_drawfog);
4094 Cvar_RegisterVariable(&r_transparentdepthmasking);
4095 Cvar_RegisterVariable(&r_texture_dds_load);
4096 Cvar_RegisterVariable(&r_texture_dds_save);
4097 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4098 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4099 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4100 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4101 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4102 Cvar_RegisterVariable(&r_textureunits);
4103 Cvar_RegisterVariable(&gl_combine);
4104 Cvar_RegisterVariable(&r_viewfbo);
4105 Cvar_RegisterVariable(&r_viewscale);
4106 Cvar_RegisterVariable(&r_glsl);
4107 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4108 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4109 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4110 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4111 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4112 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4113 Cvar_RegisterVariable(&r_glsl_postprocess);
4114 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4115 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4116 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4117 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4118 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4119 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4120 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4121 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4123 Cvar_RegisterVariable(&r_water);
4124 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4125 Cvar_RegisterVariable(&r_water_clippingplanebias);
4126 Cvar_RegisterVariable(&r_water_refractdistort);
4127 Cvar_RegisterVariable(&r_water_reflectdistort);
4128 Cvar_RegisterVariable(&r_water_scissormode);
4129 Cvar_RegisterVariable(&r_lerpsprites);
4130 Cvar_RegisterVariable(&r_lerpmodels);
4131 Cvar_RegisterVariable(&r_lerplightstyles);
4132 Cvar_RegisterVariable(&r_waterscroll);
4133 Cvar_RegisterVariable(&r_bloom);
4134 Cvar_RegisterVariable(&r_bloom_colorscale);
4135 Cvar_RegisterVariable(&r_bloom_brighten);
4136 Cvar_RegisterVariable(&r_bloom_blur);
4137 Cvar_RegisterVariable(&r_bloom_resolution);
4138 Cvar_RegisterVariable(&r_bloom_colorexponent);
4139 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4140 Cvar_RegisterVariable(&r_hdr);
4141 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4142 Cvar_RegisterVariable(&r_hdr_glowintensity);
4143 Cvar_RegisterVariable(&r_hdr_range);
4144 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4145 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4146 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4147 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4148 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4149 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4150 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4151 Cvar_RegisterVariable(&developer_texturelogging);
4152 Cvar_RegisterVariable(&gl_lightmaps);
4153 Cvar_RegisterVariable(&r_test);
4154 Cvar_RegisterVariable(&r_glsl_saturation);
4155 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4156 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4157 Cvar_RegisterVariable(&r_framedatasize);
4158 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4159 Cvar_SetValue("r_fullbrights", 0);
4160 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4162 Cvar_RegisterVariable(&r_track_sprites);
4163 Cvar_RegisterVariable(&r_track_sprites_flags);
4164 Cvar_RegisterVariable(&r_track_sprites_scalew);
4165 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4166 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4167 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4168 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4169 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4172 extern void R_Textures_Init(void);
4173 extern void GL_Draw_Init(void);
4174 extern void GL_Main_Init(void);
4175 extern void R_Shadow_Init(void);
4176 extern void R_Sky_Init(void);
4177 extern void GL_Surf_Init(void);
4178 extern void R_Particles_Init(void);
4179 extern void R_Explosion_Init(void);
4180 extern void gl_backend_init(void);
4181 extern void Sbar_Init(void);
4182 extern void R_LightningBeams_Init(void);
4183 extern void Mod_RenderInit(void);
4184 extern void Font_Init(void);
4186 void Render_Init(void)
4199 R_LightningBeams_Init();
4208 extern char *ENGINE_EXTENSIONS;
4211 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4212 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4213 gl_version = (const char *)qglGetString(GL_VERSION);
4214 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4218 if (!gl_platformextensions)
4219 gl_platformextensions = "";
4221 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4222 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4223 Con_Printf("GL_VERSION: %s\n", gl_version);
4224 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4225 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4227 VID_CheckExtensions();
4229 // LordHavoc: report supported extensions
4230 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4232 // clear to black (loading plaque will be seen over this)
4233 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4236 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4240 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4242 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4245 p = r_refdef.view.frustum + i;
4250 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4254 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4258 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4262 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4266 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4270 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4274 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4278 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4286 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4290 for (i = 0;i < numplanes;i++)
4297 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4301 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4305 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4309 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4313 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4317 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4321 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4325 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4333 //==================================================================================
4335 // LordHavoc: this stores temporary data used within the same frame
4337 typedef struct r_framedata_mem_s
4339 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4340 size_t size; // how much usable space
4341 size_t current; // how much space in use
4342 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4343 size_t wantedsize; // how much space was allocated
4344 unsigned char *data; // start of real data (16byte aligned)
4348 static r_framedata_mem_t *r_framedata_mem;
4350 void R_FrameData_Reset(void)
4352 while (r_framedata_mem)
4354 r_framedata_mem_t *next = r_framedata_mem->purge;
4355 Mem_Free(r_framedata_mem);
4356 r_framedata_mem = next;
4360 void R_FrameData_Resize(void)
4363 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4364 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4365 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4367 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4368 newmem->wantedsize = wantedsize;
4369 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4370 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4371 newmem->current = 0;
4373 newmem->purge = r_framedata_mem;
4374 r_framedata_mem = newmem;
4378 void R_FrameData_NewFrame(void)
4380 R_FrameData_Resize();
4381 if (!r_framedata_mem)
4383 // if we ran out of space on the last frame, free the old memory now
4384 while (r_framedata_mem->purge)
4386 // repeatedly remove the second item in the list, leaving only head
4387 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4388 Mem_Free(r_framedata_mem->purge);
4389 r_framedata_mem->purge = next;
4391 // reset the current mem pointer
4392 r_framedata_mem->current = 0;
4393 r_framedata_mem->mark = 0;
4396 void *R_FrameData_Alloc(size_t size)
4400 // align to 16 byte boundary - the data pointer is already aligned, so we
4401 // only need to ensure the size of every allocation is also aligned
4402 size = (size + 15) & ~15;
4404 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4406 // emergency - we ran out of space, allocate more memory
4407 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4408 R_FrameData_Resize();
4411 data = r_framedata_mem->data + r_framedata_mem->current;
4412 r_framedata_mem->current += size;
4414 // count the usage for stats
4415 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4416 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4418 return (void *)data;
4421 void *R_FrameData_Store(size_t size, void *data)
4423 void *d = R_FrameData_Alloc(size);
4425 memcpy(d, data, size);
4429 void R_FrameData_SetMark(void)
4431 if (!r_framedata_mem)
4433 r_framedata_mem->mark = r_framedata_mem->current;
4436 void R_FrameData_ReturnToMark(void)
4438 if (!r_framedata_mem)
4440 r_framedata_mem->current = r_framedata_mem->mark;
4443 //==================================================================================
4445 // LordHavoc: animcache originally written by Echon, rewritten since then
4448 * Animation cache prevents re-generating mesh data for an animated model
4449 * multiple times in one frame for lighting, shadowing, reflections, etc.
4452 void R_AnimCache_Free(void)
4456 void R_AnimCache_ClearCache(void)
4459 entity_render_t *ent;
4461 for (i = 0;i < r_refdef.scene.numentities;i++)
4463 ent = r_refdef.scene.entities[i];
4464 ent->animcache_vertex3f = NULL;
4465 ent->animcache_normal3f = NULL;
4466 ent->animcache_svector3f = NULL;
4467 ent->animcache_tvector3f = NULL;
4468 ent->animcache_vertexmesh = NULL;
4469 ent->animcache_vertex3fbuffer = NULL;
4470 ent->animcache_vertexmeshbuffer = NULL;
4474 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4478 // check if we need the meshbuffers
4479 if (!vid.useinterleavedarrays)
4482 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4483 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4484 // TODO: upload vertex3f buffer?
4485 if (ent->animcache_vertexmesh)
4487 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4488 for (i = 0;i < numvertices;i++)
4489 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4490 if (ent->animcache_svector3f)
4491 for (i = 0;i < numvertices;i++)
4492 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4493 if (ent->animcache_tvector3f)
4494 for (i = 0;i < numvertices;i++)
4495 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4496 if (ent->animcache_normal3f)
4497 for (i = 0;i < numvertices;i++)
4498 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4499 // TODO: upload vertexmeshbuffer?
4503 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4505 dp_model_t *model = ent->model;
4507 // see if it's already cached this frame
4508 if (ent->animcache_vertex3f)
4510 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4511 if (wantnormals || wanttangents)
4513 if (ent->animcache_normal3f)
4514 wantnormals = false;
4515 if (ent->animcache_svector3f)
4516 wanttangents = false;
4517 if (wantnormals || wanttangents)
4519 numvertices = model->surfmesh.num_vertices;
4521 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4524 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4525 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4527 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4528 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4534 // see if this ent is worth caching
4535 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4537 // get some memory for this entity and generate mesh data
4538 numvertices = model->surfmesh.num_vertices;
4539 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4541 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4544 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4545 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4548 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4553 void R_AnimCache_CacheVisibleEntities(void)
4556 qboolean wantnormals = true;
4557 qboolean wanttangents = !r_showsurfaces.integer;
4559 switch(vid.renderpath)
4561 case RENDERPATH_GL20:
4562 case RENDERPATH_D3D9:
4563 case RENDERPATH_D3D10:
4564 case RENDERPATH_D3D11:
4565 case RENDERPATH_GLES2:
4567 case RENDERPATH_GL13:
4568 case RENDERPATH_GL11:
4569 wanttangents = false;
4571 case RENDERPATH_SOFT:
4575 if (r_shownormals.integer)
4576 wanttangents = wantnormals = true;
4578 // TODO: thread this
4579 // NOTE: R_PrepareRTLights() also caches entities
4581 for (i = 0;i < r_refdef.scene.numentities;i++)
4582 if (r_refdef.viewcache.entityvisible[i])
4583 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4586 //==================================================================================
4588 static void R_View_UpdateEntityLighting (void)
4591 entity_render_t *ent;
4592 vec3_t tempdiffusenormal, avg;
4593 vec_t f, fa, fd, fdd;
4594 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4596 for (i = 0;i < r_refdef.scene.numentities;i++)
4598 ent = r_refdef.scene.entities[i];
4600 // skip unseen models
4601 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4605 if (ent->model && ent->model->brush.num_leafs)
4607 // TODO: use modellight for r_ambient settings on world?
4608 VectorSet(ent->modellight_ambient, 0, 0, 0);
4609 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4610 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4614 // fetch the lighting from the worldmodel data
4615 VectorClear(ent->modellight_ambient);
4616 VectorClear(ent->modellight_diffuse);
4617 VectorClear(tempdiffusenormal);
4618 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4621 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4623 // complete lightning for lit sprites
4624 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4625 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4627 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4628 org[2] = org[2] + r_overheadsprites_pushback.value;
4629 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4632 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4634 if(ent->flags & RENDER_EQUALIZE)
4636 // first fix up ambient lighting...
4637 if(r_equalize_entities_minambient.value > 0)
4639 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4642 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4643 if(fa < r_equalize_entities_minambient.value * fd)
4646 // fa'/fd' = minambient
4647 // fa'+0.25*fd' = fa+0.25*fd
4649 // fa' = fd' * minambient
4650 // fd'*(0.25+minambient) = fa+0.25*fd
4652 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4653 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4655 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4656 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
4657 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4658 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4663 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4665 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4666 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4670 // adjust brightness and saturation to target
4671 avg[0] = avg[1] = avg[2] = fa / f;
4672 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4673 avg[0] = avg[1] = avg[2] = fd / f;
4674 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4680 VectorSet(ent->modellight_ambient, 1, 1, 1);
4682 // move the light direction into modelspace coordinates for lighting code
4683 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4684 if(VectorLength2(ent->modellight_lightdir) == 0)
4685 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4686 VectorNormalize(ent->modellight_lightdir);
4690 #define MAX_LINEOFSIGHTTRACES 64
4692 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4695 vec3_t boxmins, boxmaxs;
4698 dp_model_t *model = r_refdef.scene.worldmodel;
4700 if (!model || !model->brush.TraceLineOfSight)
4703 // expand the box a little
4704 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4705 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4706 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4707 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4708 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4709 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4711 // return true if eye is inside enlarged box
4712 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4716 VectorCopy(eye, start);
4717 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4718 if (model->brush.TraceLineOfSight(model, start, end))
4721 // try various random positions
4722 for (i = 0;i < numsamples;i++)
4724 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4725 if (model->brush.TraceLineOfSight(model, start, end))
4733 static void R_View_UpdateEntityVisible (void)
4738 entity_render_t *ent;
4740 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4741 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4742 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4743 : RENDER_EXTERIORMODEL;
4744 if (!r_drawviewmodel.integer)
4745 renderimask |= RENDER_VIEWMODEL;
4746 if (!r_drawexteriormodel.integer)
4747 renderimask |= RENDER_EXTERIORMODEL;
4748 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4750 // worldmodel can check visibility
4751 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4752 for (i = 0;i < r_refdef.scene.numentities;i++)
4754 ent = r_refdef.scene.entities[i];
4755 if (!(ent->flags & renderimask))
4756 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)))
4757 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))
4758 r_refdef.viewcache.entityvisible[i] = true;
4760 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4761 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4763 for (i = 0;i < r_refdef.scene.numentities;i++)
4765 ent = r_refdef.scene.entities[i];
4766 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4768 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4770 continue; // temp entities do pvs only
4771 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4772 ent->last_trace_visibility = realtime;
4773 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4774 r_refdef.viewcache.entityvisible[i] = 0;
4781 // no worldmodel or it can't check visibility
4782 for (i = 0;i < r_refdef.scene.numentities;i++)
4784 ent = r_refdef.scene.entities[i];
4785 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));
4790 /// only used if skyrendermasked, and normally returns false
4791 int R_DrawBrushModelsSky (void)
4794 entity_render_t *ent;
4797 for (i = 0;i < r_refdef.scene.numentities;i++)
4799 if (!r_refdef.viewcache.entityvisible[i])
4801 ent = r_refdef.scene.entities[i];
4802 if (!ent->model || !ent->model->DrawSky)
4804 ent->model->DrawSky(ent);
4810 static void R_DrawNoModel(entity_render_t *ent);
4811 static void R_DrawModels(void)
4814 entity_render_t *ent;
4816 for (i = 0;i < r_refdef.scene.numentities;i++)
4818 if (!r_refdef.viewcache.entityvisible[i])
4820 ent = r_refdef.scene.entities[i];
4821 r_refdef.stats.entities++;
4822 if (ent->model && ent->model->Draw != NULL)
4823 ent->model->Draw(ent);
4829 static void R_DrawModelsDepth(void)
4832 entity_render_t *ent;
4834 for (i = 0;i < r_refdef.scene.numentities;i++)
4836 if (!r_refdef.viewcache.entityvisible[i])
4838 ent = r_refdef.scene.entities[i];
4839 if (ent->model && ent->model->DrawDepth != NULL)
4840 ent->model->DrawDepth(ent);
4844 static void R_DrawModelsDebug(void)
4847 entity_render_t *ent;
4849 for (i = 0;i < r_refdef.scene.numentities;i++)
4851 if (!r_refdef.viewcache.entityvisible[i])
4853 ent = r_refdef.scene.entities[i];
4854 if (ent->model && ent->model->DrawDebug != NULL)
4855 ent->model->DrawDebug(ent);
4859 static void R_DrawModelsAddWaterPlanes(void)
4862 entity_render_t *ent;
4864 for (i = 0;i < r_refdef.scene.numentities;i++)
4866 if (!r_refdef.viewcache.entityvisible[i])
4868 ent = r_refdef.scene.entities[i];
4869 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4870 ent->model->DrawAddWaterPlanes(ent);
4874 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4876 if (r_hdr_irisadaptation.integer)
4880 vec3_t diffusenormal;
4885 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4886 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4887 brightness = max(0.0000001f, brightness);
4888 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4889 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4890 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4891 current = r_hdr_irisadaptation_value.value;
4893 current = min(current + adjust, goal);
4894 else if (current > goal)
4895 current = max(current - adjust, goal);
4896 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4897 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4899 else if (r_hdr_irisadaptation_value.value != 1.0f)
4900 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4903 static void R_View_SetFrustum(const int *scissor)
4906 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4907 vec3_t forward, left, up, origin, v;
4911 // flipped x coordinates (because x points left here)
4912 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4913 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4915 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4916 switch(vid.renderpath)
4918 case RENDERPATH_D3D9:
4919 case RENDERPATH_D3D10:
4920 case RENDERPATH_D3D11:
4921 case RENDERPATH_SOFT:
4922 // non-flipped y coordinates
4923 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4924 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4926 case RENDERPATH_GL11:
4927 case RENDERPATH_GL13:
4928 case RENDERPATH_GL20:
4929 case RENDERPATH_GLES2:
4930 // non-flipped y coordinates
4931 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4932 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4937 // we can't trust r_refdef.view.forward and friends in reflected scenes
4938 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4941 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4942 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4943 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4944 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4945 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4946 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4947 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4948 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4949 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4950 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4951 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4952 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4956 zNear = r_refdef.nearclip;
4957 nudge = 1.0 - 1.0 / (1<<23);
4958 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4959 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4960 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4961 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4962 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4963 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4964 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4965 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4971 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4972 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4973 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4974 r_refdef.view.frustum[0].dist = m[15] - m[12];
4976 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4977 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4978 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4979 r_refdef.view.frustum[1].dist = m[15] + m[12];
4981 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4982 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4983 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4984 r_refdef.view.frustum[2].dist = m[15] - m[13];
4986 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4987 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4988 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4989 r_refdef.view.frustum[3].dist = m[15] + m[13];
4991 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4992 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4993 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4994 r_refdef.view.frustum[4].dist = m[15] - m[14];
4996 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4997 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4998 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4999 r_refdef.view.frustum[5].dist = m[15] + m[14];
5002 if (r_refdef.view.useperspective)
5004 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5005 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]);
5006 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]);
5007 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]);
5008 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]);
5010 // then the normals from the corners relative to origin
5011 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5012 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5013 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5014 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5016 // in a NORMAL view, forward cross left == up
5017 // in a REFLECTED view, forward cross left == down
5018 // so our cross products above need to be adjusted for a left handed coordinate system
5019 CrossProduct(forward, left, v);
5020 if(DotProduct(v, up) < 0)
5022 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5023 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5024 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5025 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5028 // Leaving those out was a mistake, those were in the old code, and they
5029 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5030 // I couldn't reproduce it after adding those normalizations. --blub
5031 VectorNormalize(r_refdef.view.frustum[0].normal);
5032 VectorNormalize(r_refdef.view.frustum[1].normal);
5033 VectorNormalize(r_refdef.view.frustum[2].normal);
5034 VectorNormalize(r_refdef.view.frustum[3].normal);
5036 // make the corners absolute
5037 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5038 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5039 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5040 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5043 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5045 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5046 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5047 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5048 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5049 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5053 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5054 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5055 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5056 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5057 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5058 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5059 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5060 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5061 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5062 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5064 r_refdef.view.numfrustumplanes = 5;
5066 if (r_refdef.view.useclipplane)
5068 r_refdef.view.numfrustumplanes = 6;
5069 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5072 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5073 PlaneClassify(r_refdef.view.frustum + i);
5075 // LordHavoc: note to all quake engine coders, Quake had a special case
5076 // for 90 degrees which assumed a square view (wrong), so I removed it,
5077 // Quake2 has it disabled as well.
5079 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5080 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5081 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5082 //PlaneClassify(&frustum[0]);
5084 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5085 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5086 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5087 //PlaneClassify(&frustum[1]);
5089 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5090 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5091 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5092 //PlaneClassify(&frustum[2]);
5094 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5095 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5096 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5097 //PlaneClassify(&frustum[3]);
5100 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5101 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5102 //PlaneClassify(&frustum[4]);
5105 void R_View_UpdateWithScissor(const int *myscissor)
5107 R_Main_ResizeViewCache();
5108 R_View_SetFrustum(myscissor);
5109 R_View_WorldVisibility(r_refdef.view.useclipplane);
5110 R_View_UpdateEntityVisible();
5111 R_View_UpdateEntityLighting();
5114 void R_View_Update(void)
5116 R_Main_ResizeViewCache();
5117 R_View_SetFrustum(NULL);
5118 R_View_WorldVisibility(r_refdef.view.useclipplane);
5119 R_View_UpdateEntityVisible();
5120 R_View_UpdateEntityLighting();
5123 void R_Mesh_SetMainRenderTargets(void)
5125 if (r_bloomstate.fbo_framebuffer)
5126 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5128 R_Mesh_ResetRenderTargets();
5131 void R_SetupView(qboolean allowwaterclippingplane)
5133 const float *customclipplane = NULL;
5135 int scaledwidth, scaledheight;
5136 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5138 // LordHavoc: couldn't figure out how to make this approach the
5139 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5140 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5141 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5142 dist = r_refdef.view.clipplane.dist;
5143 plane[0] = r_refdef.view.clipplane.normal[0];
5144 plane[1] = r_refdef.view.clipplane.normal[1];
5145 plane[2] = r_refdef.view.clipplane.normal[2];
5147 customclipplane = plane;
5150 scaledwidth = (int)ceil(r_refdef.view.width * bound(0.125f, r_viewscale.value, 1.0f));
5151 scaledheight = (int)ceil(r_refdef.view.height * bound(0.125f, r_viewscale.value, 1.0f));
5152 if (!r_refdef.view.useperspective)
5153 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);
5154 else if (vid.stencil && r_useinfinitefarclip.integer)
5155 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);
5157 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);
5158 R_Mesh_SetMainRenderTargets();
5159 R_SetViewport(&r_refdef.view.viewport);
5162 void R_EntityMatrix(const matrix4x4_t *matrix)
5164 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5166 gl_modelmatrixchanged = false;
5167 gl_modelmatrix = *matrix;
5168 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5169 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5170 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5171 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5173 switch(vid.renderpath)
5175 case RENDERPATH_D3D9:
5177 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5178 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5181 case RENDERPATH_D3D10:
5182 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5184 case RENDERPATH_D3D11:
5185 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5187 case RENDERPATH_GL13:
5188 case RENDERPATH_GL11:
5189 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5191 case RENDERPATH_SOFT:
5192 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5193 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5195 case RENDERPATH_GL20:
5196 case RENDERPATH_GLES2:
5197 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5198 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5204 void R_ResetViewRendering2D(void)
5206 r_viewport_t viewport;
5209 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5210 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);
5211 R_Mesh_ResetRenderTargets();
5212 R_SetViewport(&viewport);
5213 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5214 GL_Color(1, 1, 1, 1);
5215 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5216 GL_BlendFunc(GL_ONE, GL_ZERO);
5217 GL_ScissorTest(false);
5218 GL_DepthMask(false);
5219 GL_DepthRange(0, 1);
5220 GL_DepthTest(false);
5221 GL_DepthFunc(GL_LEQUAL);
5222 R_EntityMatrix(&identitymatrix);
5223 R_Mesh_ResetTextureState();
5224 GL_PolygonOffset(0, 0);
5225 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5226 switch(vid.renderpath)
5228 case RENDERPATH_GL11:
5229 case RENDERPATH_GL13:
5230 case RENDERPATH_GL20:
5231 case RENDERPATH_GLES2:
5232 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5234 case RENDERPATH_D3D9:
5235 case RENDERPATH_D3D10:
5236 case RENDERPATH_D3D11:
5237 case RENDERPATH_SOFT:
5240 GL_CullFace(GL_NONE);
5243 void R_ResetViewRendering3D(void)
5248 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5249 GL_Color(1, 1, 1, 1);
5250 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5251 GL_BlendFunc(GL_ONE, GL_ZERO);
5252 GL_ScissorTest(true);
5254 GL_DepthRange(0, 1);
5256 GL_DepthFunc(GL_LEQUAL);
5257 R_EntityMatrix(&identitymatrix);
5258 R_Mesh_ResetTextureState();
5259 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5260 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5261 switch(vid.renderpath)
5263 case RENDERPATH_GL11:
5264 case RENDERPATH_GL13:
5265 case RENDERPATH_GL20:
5266 case RENDERPATH_GLES2:
5267 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5269 case RENDERPATH_D3D9:
5270 case RENDERPATH_D3D10:
5271 case RENDERPATH_D3D11:
5272 case RENDERPATH_SOFT:
5275 GL_CullFace(r_refdef.view.cullface_back);
5280 R_RenderView_UpdateViewVectors
5283 static void R_RenderView_UpdateViewVectors(void)
5285 // break apart the view matrix into vectors for various purposes
5286 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5287 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5288 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5289 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5290 // make an inverted copy of the view matrix for tracking sprites
5291 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5294 void R_RenderScene(void);
5295 void R_RenderWaterPlanes(void);
5297 static void R_Water_StartFrame(void)
5300 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5301 r_waterstate_waterplane_t *p;
5303 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5306 switch(vid.renderpath)
5308 case RENDERPATH_GL20:
5309 case RENDERPATH_D3D9:
5310 case RENDERPATH_D3D10:
5311 case RENDERPATH_D3D11:
5312 case RENDERPATH_SOFT:
5313 case RENDERPATH_GLES2:
5315 case RENDERPATH_GL13:
5316 case RENDERPATH_GL11:
5320 // set waterwidth and waterheight to the water resolution that will be
5321 // used (often less than the screen resolution for faster rendering)
5322 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5323 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5325 // calculate desired texture sizes
5326 // can't use water if the card does not support the texture size
5327 if (!r_water.integer || r_showsurfaces.integer)
5328 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5329 else if (vid.support.arb_texture_non_power_of_two)
5331 texturewidth = waterwidth;
5332 textureheight = waterheight;
5333 camerawidth = waterwidth;
5334 cameraheight = waterheight;
5338 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5339 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5340 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5341 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5344 // allocate textures as needed
5345 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5347 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5348 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5350 if (p->texture_refraction)
5351 R_FreeTexture(p->texture_refraction);
5352 p->texture_refraction = NULL;
5353 if (p->texture_reflection)
5354 R_FreeTexture(p->texture_reflection);
5355 p->texture_reflection = NULL;
5356 if (p->texture_camera)
5357 R_FreeTexture(p->texture_camera);
5358 p->texture_camera = NULL;
5360 memset(&r_waterstate, 0, sizeof(r_waterstate));
5361 r_waterstate.texturewidth = texturewidth;
5362 r_waterstate.textureheight = textureheight;
5363 r_waterstate.camerawidth = camerawidth;
5364 r_waterstate.cameraheight = cameraheight;
5367 if (r_waterstate.texturewidth)
5369 r_waterstate.enabled = true;
5371 // when doing a reduced render (HDR) we want to use a smaller area
5372 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5373 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5375 // set up variables that will be used in shader setup
5376 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5377 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5378 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5379 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5382 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5383 r_waterstate.numwaterplanes = 0;
5386 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5388 int triangleindex, planeindex;
5394 r_waterstate_waterplane_t *p;
5395 texture_t *t = R_GetCurrentTexture(surface->texture);
5397 // just use the first triangle with a valid normal for any decisions
5398 VectorClear(normal);
5399 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5401 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5402 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5403 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5404 TriangleNormal(vert[0], vert[1], vert[2], normal);
5405 if (VectorLength2(normal) >= 0.001)
5409 VectorCopy(normal, plane.normal);
5410 VectorNormalize(plane.normal);
5411 plane.dist = DotProduct(vert[0], plane.normal);
5412 PlaneClassify(&plane);
5413 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5415 // skip backfaces (except if nocullface is set)
5416 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5418 VectorNegate(plane.normal, plane.normal);
5420 PlaneClassify(&plane);
5424 // find a matching plane if there is one
5425 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5426 if(p->camera_entity == t->camera_entity)
5427 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5429 if (planeindex >= r_waterstate.maxwaterplanes)
5430 return; // nothing we can do, out of planes
5432 // if this triangle does not fit any known plane rendered this frame, add one
5433 if (planeindex >= r_waterstate.numwaterplanes)
5435 // store the new plane
5436 r_waterstate.numwaterplanes++;
5438 // clear materialflags and pvs
5439 p->materialflags = 0;
5440 p->pvsvalid = false;
5441 p->camera_entity = t->camera_entity;
5442 VectorCopy(surface->mins, p->mins);
5443 VectorCopy(surface->maxs, p->maxs);
5448 p->mins[0] = min(p->mins[0], surface->mins[0]);
5449 p->mins[1] = min(p->mins[1], surface->mins[1]);
5450 p->mins[2] = min(p->mins[2], surface->mins[2]);
5451 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5452 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5453 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5455 // merge this surface's materialflags into the waterplane
5456 p->materialflags |= t->currentmaterialflags;
5457 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5459 // merge this surface's PVS into the waterplane
5460 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5461 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5462 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5464 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5470 static void R_Water_ProcessPlanes(void)
5473 r_refdef_view_t originalview;
5474 r_refdef_view_t myview;
5476 r_waterstate_waterplane_t *p;
5479 originalview = r_refdef.view;
5481 // make sure enough textures are allocated
5482 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5484 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5486 if (!p->texture_refraction)
5487 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);
5488 if (!p->texture_refraction)
5491 else if (p->materialflags & MATERIALFLAG_CAMERA)
5493 if (!p->texture_camera)
5494 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);
5495 if (!p->texture_camera)
5499 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5501 if (!p->texture_reflection)
5502 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);
5503 if (!p->texture_reflection)
5509 r_refdef.view = originalview;
5510 r_refdef.view.showdebug = false;
5511 r_refdef.view.width = r_waterstate.waterwidth;
5512 r_refdef.view.height = r_waterstate.waterheight;
5513 r_refdef.view.useclipplane = true;
5514 myview = r_refdef.view;
5515 r_waterstate.renderingscene = true;
5516 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5518 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5520 r_refdef.view = myview;
5521 if(r_water_scissormode.integer)
5524 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5525 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5528 // render reflected scene and copy into texture
5529 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5530 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5531 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5532 r_refdef.view.clipplane = p->plane;
5534 // reverse the cullface settings for this render
5535 r_refdef.view.cullface_front = GL_FRONT;
5536 r_refdef.view.cullface_back = GL_BACK;
5537 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5539 r_refdef.view.usecustompvs = true;
5541 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5543 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5546 R_ResetViewRendering3D();
5547 R_ClearScreen(r_refdef.fogenabled);
5548 if(r_water_scissormode.integer & 2)
5549 R_View_UpdateWithScissor(myscissor);
5552 if(r_water_scissormode.integer & 1)
5553 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5556 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);
5559 // render the normal view scene and copy into texture
5560 // (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)
5561 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5563 r_refdef.view = myview;
5564 if(r_water_scissormode.integer)
5567 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5568 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5571 r_waterstate.renderingrefraction = true;
5573 r_refdef.view.clipplane = p->plane;
5574 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5575 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5577 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5579 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5580 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5581 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5582 R_RenderView_UpdateViewVectors();
5583 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5585 r_refdef.view.usecustompvs = true;
5586 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);
5590 PlaneClassify(&r_refdef.view.clipplane);
5592 R_ResetViewRendering3D();
5593 R_ClearScreen(r_refdef.fogenabled);
5594 if(r_water_scissormode.integer & 2)
5595 R_View_UpdateWithScissor(myscissor);
5598 if(r_water_scissormode.integer & 1)
5599 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5602 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);
5603 r_waterstate.renderingrefraction = false;
5605 else if (p->materialflags & MATERIALFLAG_CAMERA)
5607 r_refdef.view = myview;
5609 r_refdef.view.clipplane = p->plane;
5610 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5611 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5613 r_refdef.view.width = r_waterstate.camerawidth;
5614 r_refdef.view.height = r_waterstate.cameraheight;
5615 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5616 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5618 if(p->camera_entity)
5620 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5621 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5624 // note: all of the view is used for displaying... so
5625 // there is no use in scissoring
5627 // reverse the cullface settings for this render
5628 r_refdef.view.cullface_front = GL_FRONT;
5629 r_refdef.view.cullface_back = GL_BACK;
5630 // also reverse the view matrix
5631 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
5632 R_RenderView_UpdateViewVectors();
5633 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5635 r_refdef.view.usecustompvs = true;
5636 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);
5639 // camera needs no clipplane
5640 r_refdef.view.useclipplane = false;
5642 PlaneClassify(&r_refdef.view.clipplane);
5644 R_ResetViewRendering3D();
5645 R_ClearScreen(r_refdef.fogenabled);
5649 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);
5650 r_waterstate.renderingrefraction = false;
5654 r_waterstate.renderingscene = false;
5655 r_refdef.view = originalview;
5656 R_ResetViewRendering3D();
5657 R_ClearScreen(r_refdef.fogenabled);
5661 r_refdef.view = originalview;
5662 r_waterstate.renderingscene = false;
5663 Cvar_SetValueQuick(&r_water, 0);
5664 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5668 void R_Bloom_StartFrame(void)
5670 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5673 switch(vid.renderpath)
5675 case RENDERPATH_GL20:
5676 case RENDERPATH_D3D9:
5677 case RENDERPATH_D3D10:
5678 case RENDERPATH_D3D11:
5679 case RENDERPATH_SOFT:
5680 case RENDERPATH_GLES2:
5682 case RENDERPATH_GL13:
5683 case RENDERPATH_GL11:
5687 // set bloomwidth and bloomheight to the bloom resolution that will be
5688 // used (often less than the screen resolution for faster rendering)
5689 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5690 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5691 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5692 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5693 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5695 // calculate desired texture sizes
5696 if (vid.support.arb_texture_non_power_of_two)
5698 screentexturewidth = vid.width;
5699 screentextureheight = vid.height;
5700 bloomtexturewidth = r_bloomstate.bloomwidth;
5701 bloomtextureheight = r_bloomstate.bloomheight;
5705 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5706 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5707 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5708 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5711 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))
5713 Cvar_SetValueQuick(&r_hdr, 0);
5714 Cvar_SetValueQuick(&r_bloom, 0);
5715 Cvar_SetValueQuick(&r_motionblur, 0);
5716 Cvar_SetValueQuick(&r_damageblur, 0);
5719 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)
5720 screentexturewidth = screentextureheight = 0;
5721 if (!r_hdr.integer && !r_bloom.integer)
5722 bloomtexturewidth = bloomtextureheight = 0;
5724 textype = TEXTYPE_COLORBUFFER;
5725 switch (vid.renderpath)
5727 case RENDERPATH_GL20:
5728 case RENDERPATH_GLES2:
5729 if (vid.support.ext_framebuffer_object)
5731 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5732 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5735 case RENDERPATH_D3D9:
5736 case RENDERPATH_D3D10:
5737 case RENDERPATH_D3D11:
5738 case RENDERPATH_SOFT:
5739 case RENDERPATH_GL13:
5740 case RENDERPATH_GL11:
5744 // allocate textures as needed
5745 if (r_bloomstate.screentexturewidth != screentexturewidth
5746 || r_bloomstate.screentextureheight != screentextureheight
5747 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5748 || r_bloomstate.bloomtextureheight != bloomtextureheight
5749 || r_bloomstate.texturetype != textype
5750 || r_bloomstate.viewfbo != r_viewfbo.integer)
5752 if (r_bloomstate.texture_bloom)
5753 R_FreeTexture(r_bloomstate.texture_bloom);
5754 r_bloomstate.texture_bloom = NULL;
5755 if (r_bloomstate.texture_screen)
5756 R_FreeTexture(r_bloomstate.texture_screen);
5757 r_bloomstate.texture_screen = NULL;
5758 if (r_bloomstate.fbo_framebuffer)
5759 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5760 r_bloomstate.fbo_framebuffer = 0;
5761 if (r_bloomstate.texture_framebuffercolor)
5762 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5763 r_bloomstate.texture_framebuffercolor = NULL;
5764 if (r_bloomstate.texture_framebufferdepth)
5765 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5766 r_bloomstate.texture_framebufferdepth = NULL;
5767 r_bloomstate.screentexturewidth = screentexturewidth;
5768 r_bloomstate.screentextureheight = screentextureheight;
5769 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5770 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);
5771 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5773 // FIXME: choose depth bits based on a cvar
5774 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5775 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);
5776 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5777 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5778 // render depth into one texture and normalmap into the other
5782 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5783 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5784 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5785 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5786 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5789 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5790 r_bloomstate.bloomtextureheight = bloomtextureheight;
5791 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5792 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);
5793 r_bloomstate.viewfbo = r_viewfbo.integer;
5794 r_bloomstate.texturetype = textype;
5797 // when doing a reduced render (HDR) we want to use a smaller area
5798 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5799 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5800 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5801 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5802 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5804 // set up a texcoord array for the full resolution screen image
5805 // (we have to keep this around to copy back during final render)
5806 r_bloomstate.screentexcoord2f[0] = 0;
5807 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.viewport.height / (float)r_bloomstate.screentextureheight;
5808 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.viewport.width / (float)r_bloomstate.screentexturewidth;
5809 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.viewport.height / (float)r_bloomstate.screentextureheight;
5810 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.viewport.width / (float)r_bloomstate.screentexturewidth;
5811 r_bloomstate.screentexcoord2f[5] = 0;
5812 r_bloomstate.screentexcoord2f[6] = 0;
5813 r_bloomstate.screentexcoord2f[7] = 0;
5815 // set up a texcoord array for the reduced resolution bloom image
5816 // (which will be additive blended over the screen image)
5817 r_bloomstate.bloomtexcoord2f[0] = 0;
5818 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5819 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5820 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5821 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5822 r_bloomstate.bloomtexcoord2f[5] = 0;
5823 r_bloomstate.bloomtexcoord2f[6] = 0;
5824 r_bloomstate.bloomtexcoord2f[7] = 0;
5826 switch(vid.renderpath)
5828 case RENDERPATH_GL11:
5829 case RENDERPATH_GL13:
5830 case RENDERPATH_GL20:
5831 case RENDERPATH_SOFT:
5832 case RENDERPATH_GLES2:
5834 case RENDERPATH_D3D9:
5835 case RENDERPATH_D3D10:
5836 case RENDERPATH_D3D11:
5839 for (i = 0;i < 4;i++)
5841 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5842 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5843 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5844 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5850 if (r_hdr.integer || r_bloom.integer)
5852 r_bloomstate.enabled = true;
5853 r_bloomstate.hdr = r_hdr.integer != 0;
5856 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);
5858 if (r_bloomstate.fbo_framebuffer)
5859 r_refdef.view.clear = true;
5862 void R_Bloom_CopyBloomTexture(float colorscale)
5864 r_refdef.stats.bloom++;
5866 // scale down screen texture to the bloom texture size
5868 R_Mesh_SetMainRenderTargets();
5869 R_SetViewport(&r_bloomstate.viewport);
5870 GL_BlendFunc(GL_ONE, GL_ZERO);
5871 GL_Color(colorscale, colorscale, colorscale, 1);
5872 // 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...
5873 switch(vid.renderpath)
5875 case RENDERPATH_GL11:
5876 case RENDERPATH_GL13:
5877 case RENDERPATH_GL20:
5878 case RENDERPATH_SOFT:
5879 case RENDERPATH_GLES2:
5880 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5882 case RENDERPATH_D3D9:
5883 case RENDERPATH_D3D10:
5884 case RENDERPATH_D3D11:
5885 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5888 // TODO: do boxfilter scale-down in shader?
5889 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5890 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5891 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5893 // we now have a bloom image in the framebuffer
5894 // copy it into the bloom image texture for later processing
5895 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);
5896 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5899 void R_Bloom_CopyHDRTexture(void)
5901 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);
5902 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5905 void R_Bloom_MakeTexture(void)
5908 float xoffset, yoffset, r, brighten;
5910 r_refdef.stats.bloom++;
5912 R_ResetViewRendering2D();
5914 // we have a bloom image in the framebuffer
5916 R_SetViewport(&r_bloomstate.viewport);
5918 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5921 r = bound(0, r_bloom_colorexponent.value / x, 1);
5922 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5924 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5925 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5926 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5927 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5929 // copy the vertically blurred bloom view to a texture
5930 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);
5931 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5934 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5935 brighten = r_bloom_brighten.value;
5937 brighten *= r_hdr_range.value;
5938 brighten = sqrt(brighten);
5940 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5941 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5943 for (dir = 0;dir < 2;dir++)
5945 // blend on at multiple vertical offsets to achieve a vertical blur
5946 // TODO: do offset blends using GLSL
5947 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5948 GL_BlendFunc(GL_ONE, GL_ZERO);
5949 for (x = -range;x <= range;x++)
5951 if (!dir){xoffset = 0;yoffset = x;}
5952 else {xoffset = x;yoffset = 0;}
5953 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5954 yoffset /= (float)r_bloomstate.bloomtextureheight;
5955 // compute a texcoord array with the specified x and y offset
5956 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5957 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5958 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5959 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5960 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5961 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5962 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5963 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5964 // this r value looks like a 'dot' particle, fading sharply to
5965 // black at the edges
5966 // (probably not realistic but looks good enough)
5967 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5968 //r = brighten/(range*2+1);
5969 r = brighten / (range * 2 + 1);
5971 r *= (1 - x*x/(float)(range*range));
5972 GL_Color(r, r, r, 1);
5973 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5974 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5975 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5976 GL_BlendFunc(GL_ONE, GL_ONE);
5979 // copy the vertically blurred bloom view to a texture
5980 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);
5981 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5985 void R_HDR_RenderBloomTexture(void)
5987 int oldwidth, oldheight;
5988 float oldcolorscale;
5989 qboolean oldwaterstate;
5991 oldwaterstate = r_waterstate.enabled;
5992 oldcolorscale = r_refdef.view.colorscale;
5993 oldwidth = r_refdef.view.width;
5994 oldheight = r_refdef.view.height;
5995 r_refdef.view.width = r_bloomstate.bloomwidth;
5996 r_refdef.view.height = r_bloomstate.bloomheight;
5998 if(r_hdr.integer < 2)
5999 r_waterstate.enabled = false;
6001 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6002 // TODO: add exposure compensation features
6003 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6005 r_refdef.view.showdebug = false;
6006 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6008 R_ResetViewRendering3D();
6010 R_ClearScreen(r_refdef.fogenabled);
6011 if (r_timereport_active)
6012 R_TimeReport("HDRclear");
6015 if (r_timereport_active)
6016 R_TimeReport("visibility");
6018 // only do secondary renders with HDR if r_hdr is 2 or higher
6019 r_waterstate.numwaterplanes = 0;
6020 if (r_waterstate.enabled)
6021 R_RenderWaterPlanes();
6023 r_refdef.view.showdebug = true;
6025 r_waterstate.numwaterplanes = 0;
6027 R_ResetViewRendering2D();
6029 R_Bloom_CopyHDRTexture();
6030 R_Bloom_MakeTexture();
6032 // restore the view settings
6033 r_waterstate.enabled = oldwaterstate;
6034 r_refdef.view.width = oldwidth;
6035 r_refdef.view.height = oldheight;
6036 r_refdef.view.colorscale = oldcolorscale;
6038 R_ResetViewRendering3D();
6040 R_ClearScreen(r_refdef.fogenabled);
6041 if (r_timereport_active)
6042 R_TimeReport("viewclear");
6045 static void R_BlendView(void)
6047 unsigned int permutation;
6048 float uservecs[4][4];
6050 switch (vid.renderpath)
6052 case RENDERPATH_GL20:
6053 case RENDERPATH_D3D9:
6054 case RENDERPATH_D3D10:
6055 case RENDERPATH_D3D11:
6056 case RENDERPATH_SOFT:
6057 case RENDERPATH_GLES2:
6059 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6060 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6061 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6062 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6063 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6065 if (r_bloomstate.texture_screen)
6067 // make sure the buffer is available
6068 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6070 R_ResetViewRendering2D();
6071 R_Mesh_SetMainRenderTargets();
6073 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6075 // declare variables
6077 static float avgspeed;
6079 speed = VectorLength(cl.movement_velocity);
6081 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6082 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6084 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6085 speed = bound(0, speed, 1);
6086 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6088 // calculate values into a standard alpha
6089 cl.motionbluralpha = 1 - exp(-
6091 (r_motionblur.value * speed / 80)
6093 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6096 max(0.0001, cl.time - cl.oldtime) // fps independent
6099 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6100 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6102 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6104 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6105 GL_Color(1, 1, 1, cl.motionbluralpha);
6106 switch(vid.renderpath)
6108 case RENDERPATH_GL11:
6109 case RENDERPATH_GL13:
6110 case RENDERPATH_GL20:
6111 case RENDERPATH_SOFT:
6112 case RENDERPATH_GLES2:
6113 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6115 case RENDERPATH_D3D9:
6116 case RENDERPATH_D3D10:
6117 case RENDERPATH_D3D11:
6118 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6121 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6122 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6123 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6127 // copy view into the screen texture
6128 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);
6129 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6131 else if (!r_bloomstate.texture_bloom)
6133 // we may still have to do view tint...
6134 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6136 // apply a color tint to the whole view
6137 R_ResetViewRendering2D();
6138 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6139 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6140 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6141 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6142 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6144 break; // no screen processing, no bloom, skip it
6147 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6149 // render simple bloom effect
6150 // copy the screen and shrink it and darken it for the bloom process
6151 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6152 // make the bloom texture
6153 R_Bloom_MakeTexture();
6156 #if _MSC_VER >= 1400
6157 #define sscanf sscanf_s
6159 memset(uservecs, 0, sizeof(uservecs));
6160 if (r_glsl_postprocess_uservec1_enable.integer)
6161 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6162 if (r_glsl_postprocess_uservec2_enable.integer)
6163 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6164 if (r_glsl_postprocess_uservec3_enable.integer)
6165 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6166 if (r_glsl_postprocess_uservec4_enable.integer)
6167 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6169 R_ResetViewRendering2D();
6170 GL_Color(1, 1, 1, 1);
6171 GL_BlendFunc(GL_ONE, GL_ZERO);
6173 switch(vid.renderpath)
6175 case RENDERPATH_GL20:
6176 case RENDERPATH_GLES2:
6177 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6178 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6179 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6180 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6181 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6182 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]);
6183 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6184 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]);
6185 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]);
6186 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]);
6187 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]);
6188 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6189 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6190 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);
6192 case RENDERPATH_D3D9:
6194 // 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...
6195 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6196 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6197 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6198 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6199 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6200 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6201 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6202 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6203 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6204 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6205 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6206 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6207 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6208 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6211 case RENDERPATH_D3D10:
6212 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6214 case RENDERPATH_D3D11:
6215 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6217 case RENDERPATH_SOFT:
6218 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6219 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6220 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6221 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6222 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6223 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6224 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6225 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6226 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6227 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6228 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6229 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6230 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6231 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6236 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6237 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6239 case RENDERPATH_GL13:
6240 case RENDERPATH_GL11:
6241 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6243 // apply a color tint to the whole view
6244 R_ResetViewRendering2D();
6245 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6246 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6247 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6248 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6249 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6255 matrix4x4_t r_waterscrollmatrix;
6257 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6259 if (r_refdef.fog_density)
6261 r_refdef.fogcolor[0] = r_refdef.fog_red;
6262 r_refdef.fogcolor[1] = r_refdef.fog_green;
6263 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6265 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6266 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6267 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6268 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6272 VectorCopy(r_refdef.fogcolor, fogvec);
6273 // color.rgb *= ContrastBoost * SceneBrightness;
6274 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6275 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6276 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6277 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6282 void R_UpdateVariables(void)
6286 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6288 r_refdef.farclip = r_farclip_base.value;
6289 if (r_refdef.scene.worldmodel)
6290 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6291 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6293 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6294 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6295 r_refdef.polygonfactor = 0;
6296 r_refdef.polygonoffset = 0;
6297 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6298 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6300 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6301 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6302 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6303 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6304 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6305 if (FAKELIGHT_ENABLED)
6307 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6309 if (r_showsurfaces.integer)
6311 r_refdef.scene.rtworld = false;
6312 r_refdef.scene.rtworldshadows = false;
6313 r_refdef.scene.rtdlight = false;
6314 r_refdef.scene.rtdlightshadows = false;
6315 r_refdef.lightmapintensity = 0;
6318 if (gamemode == GAME_NEHAHRA)
6320 if (gl_fogenable.integer)
6322 r_refdef.oldgl_fogenable = true;
6323 r_refdef.fog_density = gl_fogdensity.value;
6324 r_refdef.fog_red = gl_fogred.value;
6325 r_refdef.fog_green = gl_foggreen.value;
6326 r_refdef.fog_blue = gl_fogblue.value;
6327 r_refdef.fog_alpha = 1;
6328 r_refdef.fog_start = 0;
6329 r_refdef.fog_end = gl_skyclip.value;
6330 r_refdef.fog_height = 1<<30;
6331 r_refdef.fog_fadedepth = 128;
6333 else if (r_refdef.oldgl_fogenable)
6335 r_refdef.oldgl_fogenable = false;
6336 r_refdef.fog_density = 0;
6337 r_refdef.fog_red = 0;
6338 r_refdef.fog_green = 0;
6339 r_refdef.fog_blue = 0;
6340 r_refdef.fog_alpha = 0;
6341 r_refdef.fog_start = 0;
6342 r_refdef.fog_end = 0;
6343 r_refdef.fog_height = 1<<30;
6344 r_refdef.fog_fadedepth = 128;
6348 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6349 r_refdef.fog_start = max(0, r_refdef.fog_start);
6350 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6352 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6354 if (r_refdef.fog_density && r_drawfog.integer)
6356 r_refdef.fogenabled = true;
6357 // this is the point where the fog reaches 0.9986 alpha, which we
6358 // consider a good enough cutoff point for the texture
6359 // (0.9986 * 256 == 255.6)
6360 if (r_fog_exp2.integer)
6361 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6363 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6364 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6365 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6366 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6367 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6368 R_BuildFogHeightTexture();
6369 // fog color was already set
6370 // update the fog texture
6371 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)
6372 R_BuildFogTexture();
6373 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6374 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6377 r_refdef.fogenabled = false;
6379 switch(vid.renderpath)
6381 case RENDERPATH_GL20:
6382 case RENDERPATH_D3D9:
6383 case RENDERPATH_D3D10:
6384 case RENDERPATH_D3D11:
6385 case RENDERPATH_SOFT:
6386 case RENDERPATH_GLES2:
6387 if(v_glslgamma.integer && !vid_gammatables_trivial)
6389 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6391 // build GLSL gamma texture
6392 #define RAMPWIDTH 256
6393 unsigned short ramp[RAMPWIDTH * 3];
6394 unsigned char rampbgr[RAMPWIDTH][4];
6397 r_texture_gammaramps_serial = vid_gammatables_serial;
6399 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6400 for(i = 0; i < RAMPWIDTH; ++i)
6402 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6403 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6404 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6407 if (r_texture_gammaramps)
6409 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6413 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6419 // remove GLSL gamma texture
6422 case RENDERPATH_GL13:
6423 case RENDERPATH_GL11:
6428 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6429 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6435 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6436 if( scenetype != r_currentscenetype ) {
6437 // store the old scenetype
6438 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6439 r_currentscenetype = scenetype;
6440 // move in the new scene
6441 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6450 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6452 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6453 if( scenetype == r_currentscenetype ) {
6454 return &r_refdef.scene;
6456 return &r_scenes_store[ scenetype ];
6465 int dpsoftrast_test;
6466 void R_RenderView(void)
6468 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6470 dpsoftrast_test = r_test.integer;
6472 if (r_timereport_active)
6473 R_TimeReport("start");
6474 r_textureframe++; // used only by R_GetCurrentTexture
6475 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6477 if(R_CompileShader_CheckStaticParms())
6480 if (!r_drawentities.integer)
6481 r_refdef.scene.numentities = 0;
6483 R_AnimCache_ClearCache();
6484 R_FrameData_NewFrame();
6486 /* adjust for stereo display */
6487 if(R_Stereo_Active())
6489 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);
6490 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6493 if (r_refdef.view.isoverlay)
6495 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6496 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6497 R_TimeReport("depthclear");
6499 r_refdef.view.showdebug = false;
6501 r_waterstate.enabled = false;
6502 r_waterstate.numwaterplanes = 0;
6506 r_refdef.view.matrix = originalmatrix;
6512 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6514 r_refdef.view.matrix = originalmatrix;
6515 return; //Host_Error ("R_RenderView: NULL worldmodel");
6518 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6520 R_RenderView_UpdateViewVectors();
6522 R_Shadow_UpdateWorldLightSelection();
6524 R_Bloom_StartFrame();
6525 R_Water_StartFrame();
6528 if (r_timereport_active)
6529 R_TimeReport("viewsetup");
6531 R_ResetViewRendering3D();
6533 if (r_refdef.view.clear || r_refdef.fogenabled)
6535 R_ClearScreen(r_refdef.fogenabled);
6536 if (r_timereport_active)
6537 R_TimeReport("viewclear");
6539 r_refdef.view.clear = true;
6541 // this produces a bloom texture to be used in R_BlendView() later
6542 if (r_hdr.integer && r_bloomstate.bloomwidth)
6544 R_HDR_RenderBloomTexture();
6545 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6546 r_textureframe++; // used only by R_GetCurrentTexture
6549 r_refdef.view.showdebug = true;
6552 if (r_timereport_active)
6553 R_TimeReport("visibility");
6555 r_waterstate.numwaterplanes = 0;
6556 if (r_waterstate.enabled)
6557 R_RenderWaterPlanes();
6560 r_waterstate.numwaterplanes = 0;
6563 if (r_timereport_active)
6564 R_TimeReport("blendview");
6566 GL_Scissor(0, 0, vid.width, vid.height);
6567 GL_ScissorTest(false);
6569 r_refdef.view.matrix = originalmatrix;
6574 void R_RenderWaterPlanes(void)
6576 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6578 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6579 if (r_timereport_active)
6580 R_TimeReport("waterworld");
6583 // don't let sound skip if going slow
6584 if (r_refdef.scene.extraupdate)
6587 R_DrawModelsAddWaterPlanes();
6588 if (r_timereport_active)
6589 R_TimeReport("watermodels");
6591 if (r_waterstate.numwaterplanes)
6593 R_Water_ProcessPlanes();
6594 if (r_timereport_active)
6595 R_TimeReport("waterscenes");
6599 extern void R_DrawLightningBeams (void);
6600 extern void VM_CL_AddPolygonsToMeshQueue (void);
6601 extern void R_DrawPortals (void);
6602 extern cvar_t cl_locs_show;
6603 static void R_DrawLocs(void);
6604 static void R_DrawEntityBBoxes(void);
6605 static void R_DrawModelDecals(void);
6606 extern void R_DrawModelShadows(void);
6607 extern void R_DrawModelShadowMaps(void);
6608 extern cvar_t cl_decals_newsystem;
6609 extern qboolean r_shadow_usingdeferredprepass;
6610 void R_RenderScene(void)
6612 qboolean shadowmapping = false;
6614 if (r_timereport_active)
6615 R_TimeReport("beginscene");
6617 r_refdef.stats.renders++;
6621 // don't let sound skip if going slow
6622 if (r_refdef.scene.extraupdate)
6625 R_MeshQueue_BeginScene();
6629 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);
6631 if (r_timereport_active)
6632 R_TimeReport("skystartframe");
6634 if (cl.csqc_vidvars.drawworld)
6636 // don't let sound skip if going slow
6637 if (r_refdef.scene.extraupdate)
6640 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6642 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6643 if (r_timereport_active)
6644 R_TimeReport("worldsky");
6647 if (R_DrawBrushModelsSky() && r_timereport_active)
6648 R_TimeReport("bmodelsky");
6650 if (skyrendermasked && skyrenderlater)
6652 // we have to force off the water clipping plane while rendering sky
6656 if (r_timereport_active)
6657 R_TimeReport("sky");
6661 R_AnimCache_CacheVisibleEntities();
6662 if (r_timereport_active)
6663 R_TimeReport("animation");
6665 R_Shadow_PrepareLights();
6666 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6667 R_Shadow_PrepareModelShadows();
6668 if (r_timereport_active)
6669 R_TimeReport("preparelights");
6671 if (R_Shadow_ShadowMappingEnabled())
6672 shadowmapping = true;
6674 if (r_shadow_usingdeferredprepass)
6675 R_Shadow_DrawPrepass();
6677 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6679 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6680 if (r_timereport_active)
6681 R_TimeReport("worlddepth");
6683 if (r_depthfirst.integer >= 2)
6685 R_DrawModelsDepth();
6686 if (r_timereport_active)
6687 R_TimeReport("modeldepth");
6690 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6692 R_DrawModelShadowMaps();
6693 R_ResetViewRendering3D();
6694 // don't let sound skip if going slow
6695 if (r_refdef.scene.extraupdate)
6699 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6701 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6702 if (r_timereport_active)
6703 R_TimeReport("world");
6706 // don't let sound skip if going slow
6707 if (r_refdef.scene.extraupdate)
6711 if (r_timereport_active)
6712 R_TimeReport("models");
6714 // don't let sound skip if going slow
6715 if (r_refdef.scene.extraupdate)
6718 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6720 R_DrawModelShadows();
6721 R_ResetViewRendering3D();
6722 // don't let sound skip if going slow
6723 if (r_refdef.scene.extraupdate)
6727 if (!r_shadow_usingdeferredprepass)
6729 R_Shadow_DrawLights();
6730 if (r_timereport_active)
6731 R_TimeReport("rtlights");
6734 // don't let sound skip if going slow
6735 if (r_refdef.scene.extraupdate)
6738 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6740 R_DrawModelShadows();
6741 R_ResetViewRendering3D();
6742 // don't let sound skip if going slow
6743 if (r_refdef.scene.extraupdate)
6747 if (cl.csqc_vidvars.drawworld)
6749 if (cl_decals_newsystem.integer)
6751 R_DrawModelDecals();
6752 if (r_timereport_active)
6753 R_TimeReport("modeldecals");
6758 if (r_timereport_active)
6759 R_TimeReport("decals");
6763 if (r_timereport_active)
6764 R_TimeReport("particles");
6767 if (r_timereport_active)
6768 R_TimeReport("explosions");
6770 R_DrawLightningBeams();
6771 if (r_timereport_active)
6772 R_TimeReport("lightning");
6775 VM_CL_AddPolygonsToMeshQueue();
6777 if (r_refdef.view.showdebug)
6779 if (cl_locs_show.integer)
6782 if (r_timereport_active)
6783 R_TimeReport("showlocs");
6786 if (r_drawportals.integer)
6789 if (r_timereport_active)
6790 R_TimeReport("portals");
6793 if (r_showbboxes.value > 0)
6795 R_DrawEntityBBoxes();
6796 if (r_timereport_active)
6797 R_TimeReport("bboxes");
6801 R_MeshQueue_RenderTransparent();
6802 if (r_timereport_active)
6803 R_TimeReport("drawtrans");
6805 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))
6807 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6808 if (r_timereport_active)
6809 R_TimeReport("worlddebug");
6810 R_DrawModelsDebug();
6811 if (r_timereport_active)
6812 R_TimeReport("modeldebug");
6815 if (cl.csqc_vidvars.drawworld)
6817 R_Shadow_DrawCoronas();
6818 if (r_timereport_active)
6819 R_TimeReport("coronas");
6824 GL_DepthTest(false);
6825 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6826 GL_Color(1, 1, 1, 1);
6827 qglBegin(GL_POLYGON);
6828 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6829 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6830 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6831 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6833 qglBegin(GL_POLYGON);
6834 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]);
6835 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]);
6836 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]);
6837 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]);
6839 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6843 // don't let sound skip if going slow
6844 if (r_refdef.scene.extraupdate)
6847 R_ResetViewRendering2D();
6850 static const unsigned short bboxelements[36] =
6860 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6863 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6865 RSurf_ActiveWorldEntity();
6867 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6868 GL_DepthMask(false);
6869 GL_DepthRange(0, 1);
6870 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6871 // R_Mesh_ResetTextureState();
6873 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6874 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6875 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6876 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6877 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6878 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6879 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6880 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6881 R_FillColors(color4f, 8, cr, cg, cb, ca);
6882 if (r_refdef.fogenabled)
6884 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6886 f1 = RSurf_FogVertex(v);
6888 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6889 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6890 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6893 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6894 R_Mesh_ResetTextureState();
6895 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6896 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6899 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6903 prvm_edict_t *edict;
6904 prvm_prog_t *prog_save = prog;
6906 // this function draws bounding boxes of server entities
6910 GL_CullFace(GL_NONE);
6911 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6915 for (i = 0;i < numsurfaces;i++)
6917 edict = PRVM_EDICT_NUM(surfacelist[i]);
6918 switch ((int)edict->fields.server->solid)
6920 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6921 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6922 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6923 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6924 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6925 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6927 color[3] *= r_showbboxes.value;
6928 color[3] = bound(0, color[3], 1);
6929 GL_DepthTest(!r_showdisabledepthtest.integer);
6930 GL_CullFace(r_refdef.view.cullface_front);
6931 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6937 static void R_DrawEntityBBoxes(void)
6940 prvm_edict_t *edict;
6942 prvm_prog_t *prog_save = prog;
6944 // this function draws bounding boxes of server entities
6950 for (i = 0;i < prog->num_edicts;i++)
6952 edict = PRVM_EDICT_NUM(i);
6953 if (edict->priv.server->free)
6955 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6956 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6958 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6960 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6961 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6967 static const int nomodelelement3i[24] =
6979 static const unsigned short nomodelelement3s[24] =
6991 static const float nomodelvertex3f[6*3] =
7001 static const float nomodelcolor4f[6*4] =
7003 0.0f, 0.0f, 0.5f, 1.0f,
7004 0.0f, 0.0f, 0.5f, 1.0f,
7005 0.0f, 0.5f, 0.0f, 1.0f,
7006 0.0f, 0.5f, 0.0f, 1.0f,
7007 0.5f, 0.0f, 0.0f, 1.0f,
7008 0.5f, 0.0f, 0.0f, 1.0f
7011 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7017 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);
7019 // this is only called once per entity so numsurfaces is always 1, and
7020 // surfacelist is always {0}, so this code does not handle batches
7022 if (rsurface.ent_flags & RENDER_ADDITIVE)
7024 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7025 GL_DepthMask(false);
7027 else if (rsurface.colormod[3] < 1)
7029 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7030 GL_DepthMask(false);
7034 GL_BlendFunc(GL_ONE, GL_ZERO);
7037 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7038 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7039 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7040 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7041 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7042 for (i = 0, c = color4f;i < 6;i++, c += 4)
7044 c[0] *= rsurface.colormod[0];
7045 c[1] *= rsurface.colormod[1];
7046 c[2] *= rsurface.colormod[2];
7047 c[3] *= rsurface.colormod[3];
7049 if (r_refdef.fogenabled)
7051 for (i = 0, c = color4f;i < 6;i++, c += 4)
7053 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7055 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7056 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7057 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7060 // R_Mesh_ResetTextureState();
7061 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7062 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7063 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7066 void R_DrawNoModel(entity_render_t *ent)
7069 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7070 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7071 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7073 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7076 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7078 vec3_t right1, right2, diff, normal;
7080 VectorSubtract (org2, org1, normal);
7082 // calculate 'right' vector for start
7083 VectorSubtract (r_refdef.view.origin, org1, diff);
7084 CrossProduct (normal, diff, right1);
7085 VectorNormalize (right1);
7087 // calculate 'right' vector for end
7088 VectorSubtract (r_refdef.view.origin, org2, diff);
7089 CrossProduct (normal, diff, right2);
7090 VectorNormalize (right2);
7092 vert[ 0] = org1[0] + width * right1[0];
7093 vert[ 1] = org1[1] + width * right1[1];
7094 vert[ 2] = org1[2] + width * right1[2];
7095 vert[ 3] = org1[0] - width * right1[0];
7096 vert[ 4] = org1[1] - width * right1[1];
7097 vert[ 5] = org1[2] - width * right1[2];
7098 vert[ 6] = org2[0] - width * right2[0];
7099 vert[ 7] = org2[1] - width * right2[1];
7100 vert[ 8] = org2[2] - width * right2[2];
7101 vert[ 9] = org2[0] + width * right2[0];
7102 vert[10] = org2[1] + width * right2[1];
7103 vert[11] = org2[2] + width * right2[2];
7106 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)
7108 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7109 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7110 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7111 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7112 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7113 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7114 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7115 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7116 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7117 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7118 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7119 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7122 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7127 VectorSet(v, x, y, z);
7128 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7129 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7131 if (i == mesh->numvertices)
7133 if (mesh->numvertices < mesh->maxvertices)
7135 VectorCopy(v, vertex3f);
7136 mesh->numvertices++;
7138 return mesh->numvertices;
7144 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7148 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7149 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7150 e = mesh->element3i + mesh->numtriangles * 3;
7151 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7153 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7154 if (mesh->numtriangles < mesh->maxtriangles)
7159 mesh->numtriangles++;
7161 element[1] = element[2];
7165 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7169 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7170 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7171 e = mesh->element3i + mesh->numtriangles * 3;
7172 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7174 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7175 if (mesh->numtriangles < mesh->maxtriangles)
7180 mesh->numtriangles++;
7182 element[1] = element[2];
7186 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7187 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7189 int planenum, planenum2;
7192 mplane_t *plane, *plane2;
7194 double temppoints[2][256*3];
7195 // figure out how large a bounding box we need to properly compute this brush
7197 for (w = 0;w < numplanes;w++)
7198 maxdist = max(maxdist, fabs(planes[w].dist));
7199 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7200 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7201 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7205 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7206 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7208 if (planenum2 == planenum)
7210 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);
7213 if (tempnumpoints < 3)
7215 // generate elements forming a triangle fan for this polygon
7216 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7220 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)
7222 texturelayer_t *layer;
7223 layer = t->currentlayers + t->currentnumlayers++;
7225 layer->depthmask = depthmask;
7226 layer->blendfunc1 = blendfunc1;
7227 layer->blendfunc2 = blendfunc2;
7228 layer->texture = texture;
7229 layer->texmatrix = *matrix;
7230 layer->color[0] = r;
7231 layer->color[1] = g;
7232 layer->color[2] = b;
7233 layer->color[3] = a;
7236 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7238 if(parms[0] == 0 && parms[1] == 0)
7240 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7241 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7246 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7249 index = parms[2] + r_refdef.scene.time * parms[3];
7250 index -= floor(index);
7251 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7254 case Q3WAVEFUNC_NONE:
7255 case Q3WAVEFUNC_NOISE:
7256 case Q3WAVEFUNC_COUNT:
7259 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7260 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7261 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7262 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7263 case Q3WAVEFUNC_TRIANGLE:
7265 f = index - floor(index);
7276 f = parms[0] + parms[1] * f;
7277 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7278 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7282 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7287 matrix4x4_t matrix, temp;
7288 switch(tcmod->tcmod)
7292 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7293 matrix = r_waterscrollmatrix;
7295 matrix = identitymatrix;
7297 case Q3TCMOD_ENTITYTRANSLATE:
7298 // this is used in Q3 to allow the gamecode to control texcoord
7299 // scrolling on the entity, which is not supported in darkplaces yet.
7300 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7302 case Q3TCMOD_ROTATE:
7303 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7304 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7305 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7308 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7310 case Q3TCMOD_SCROLL:
7311 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7313 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7314 w = (int) tcmod->parms[0];
7315 h = (int) tcmod->parms[1];
7316 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7318 idx = (int) floor(f * w * h);
7319 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7321 case Q3TCMOD_STRETCH:
7322 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7323 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7325 case Q3TCMOD_TRANSFORM:
7326 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7327 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7328 VectorSet(tcmat + 6, 0 , 0 , 1);
7329 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7330 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7332 case Q3TCMOD_TURBULENT:
7333 // this is handled in the RSurf_PrepareVertices function
7334 matrix = identitymatrix;
7338 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7341 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7343 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7344 char name[MAX_QPATH];
7345 skinframe_t *skinframe;
7346 unsigned char pixels[296*194];
7347 strlcpy(cache->name, skinname, sizeof(cache->name));
7348 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7349 if (developer_loading.integer)
7350 Con_Printf("loading %s\n", name);
7351 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7352 if (!skinframe || !skinframe->base)
7355 fs_offset_t filesize;
7357 f = FS_LoadFile(name, tempmempool, true, &filesize);
7360 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7361 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7365 cache->skinframe = skinframe;
7368 texture_t *R_GetCurrentTexture(texture_t *t)
7371 const entity_render_t *ent = rsurface.entity;
7372 dp_model_t *model = ent->model;
7373 q3shaderinfo_layer_tcmod_t *tcmod;
7375 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7376 return t->currentframe;
7377 t->update_lastrenderframe = r_textureframe;
7378 t->update_lastrenderentity = (void *)ent;
7380 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7381 t->camera_entity = ent->entitynumber;
7383 t->camera_entity = 0;
7385 // switch to an alternate material if this is a q1bsp animated material
7387 texture_t *texture = t;
7388 int s = rsurface.ent_skinnum;
7389 if ((unsigned int)s >= (unsigned int)model->numskins)
7391 if (model->skinscenes)
7393 if (model->skinscenes[s].framecount > 1)
7394 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7396 s = model->skinscenes[s].firstframe;
7399 t = t + s * model->num_surfaces;
7402 // use an alternate animation if the entity's frame is not 0,
7403 // and only if the texture has an alternate animation
7404 if (rsurface.ent_alttextures && t->anim_total[1])
7405 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7407 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7409 texture->currentframe = t;
7412 // update currentskinframe to be a qw skin or animation frame
7413 if (rsurface.ent_qwskin >= 0)
7415 i = rsurface.ent_qwskin;
7416 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7418 r_qwskincache_size = cl.maxclients;
7420 Mem_Free(r_qwskincache);
7421 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7423 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7424 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7425 t->currentskinframe = r_qwskincache[i].skinframe;
7426 if (t->currentskinframe == NULL)
7427 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7429 else if (t->numskinframes >= 2)
7430 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7431 if (t->backgroundnumskinframes >= 2)
7432 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7434 t->currentmaterialflags = t->basematerialflags;
7435 t->currentalpha = rsurface.colormod[3];
7436 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7437 t->currentalpha *= r_wateralpha.value;
7438 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7439 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7440 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7441 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7442 if (!(rsurface.ent_flags & RENDER_LIGHT))
7443 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7444 else if (FAKELIGHT_ENABLED)
7446 // no modellight if using fakelight for the map
7448 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7450 // pick a model lighting mode
7451 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7452 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7454 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7456 if (rsurface.ent_flags & RENDER_ADDITIVE)
7457 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7458 else if (t->currentalpha < 1)
7459 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7460 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7461 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7462 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7463 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7464 if (t->backgroundnumskinframes)
7465 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7466 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7468 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7469 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7472 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7473 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7474 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7476 // there is no tcmod
7477 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7479 t->currenttexmatrix = r_waterscrollmatrix;
7480 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7482 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7484 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7485 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7488 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7489 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7490 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7491 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7493 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7494 if (t->currentskinframe->qpixels)
7495 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7496 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7497 if (!t->basetexture)
7498 t->basetexture = r_texture_notexture;
7499 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7500 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7501 t->nmaptexture = t->currentskinframe->nmap;
7502 if (!t->nmaptexture)
7503 t->nmaptexture = r_texture_blanknormalmap;
7504 t->glosstexture = r_texture_black;
7505 t->glowtexture = t->currentskinframe->glow;
7506 t->fogtexture = t->currentskinframe->fog;
7507 t->reflectmasktexture = t->currentskinframe->reflect;
7508 if (t->backgroundnumskinframes)
7510 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7511 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7512 t->backgroundglosstexture = r_texture_black;
7513 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7514 if (!t->backgroundnmaptexture)
7515 t->backgroundnmaptexture = r_texture_blanknormalmap;
7519 t->backgroundbasetexture = r_texture_white;
7520 t->backgroundnmaptexture = r_texture_blanknormalmap;
7521 t->backgroundglosstexture = r_texture_black;
7522 t->backgroundglowtexture = NULL;
7524 t->specularpower = r_shadow_glossexponent.value;
7525 // TODO: store reference values for these in the texture?
7526 t->specularscale = 0;
7527 if (r_shadow_gloss.integer > 0)
7529 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7531 if (r_shadow_glossintensity.value > 0)
7533 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7534 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7535 t->specularscale = r_shadow_glossintensity.value;
7538 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7540 t->glosstexture = r_texture_white;
7541 t->backgroundglosstexture = r_texture_white;
7542 t->specularscale = r_shadow_gloss2intensity.value;
7543 t->specularpower = r_shadow_gloss2exponent.value;
7546 t->specularscale *= t->specularscalemod;
7547 t->specularpower *= t->specularpowermod;
7549 // lightmaps mode looks bad with dlights using actual texturing, so turn
7550 // off the colormap and glossmap, but leave the normalmap on as it still
7551 // accurately represents the shading involved
7552 if (gl_lightmaps.integer)
7554 t->basetexture = r_texture_grey128;
7555 t->pantstexture = r_texture_black;
7556 t->shirttexture = r_texture_black;
7557 t->nmaptexture = r_texture_blanknormalmap;
7558 t->glosstexture = r_texture_black;
7559 t->glowtexture = NULL;
7560 t->fogtexture = NULL;
7561 t->reflectmasktexture = NULL;
7562 t->backgroundbasetexture = NULL;
7563 t->backgroundnmaptexture = r_texture_blanknormalmap;
7564 t->backgroundglosstexture = r_texture_black;
7565 t->backgroundglowtexture = NULL;
7566 t->specularscale = 0;
7567 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7570 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7571 VectorClear(t->dlightcolor);
7572 t->currentnumlayers = 0;
7573 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7575 int blendfunc1, blendfunc2;
7577 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7579 blendfunc1 = GL_SRC_ALPHA;
7580 blendfunc2 = GL_ONE;
7582 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7584 blendfunc1 = GL_SRC_ALPHA;
7585 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7587 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7589 blendfunc1 = t->customblendfunc[0];
7590 blendfunc2 = t->customblendfunc[1];
7594 blendfunc1 = GL_ONE;
7595 blendfunc2 = GL_ZERO;
7597 // don't colormod evilblend textures
7598 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7599 VectorSet(t->lightmapcolor, 1, 1, 1);
7600 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7601 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7603 // fullbright is not affected by r_refdef.lightmapintensity
7604 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]);
7605 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7606 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]);
7607 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7608 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]);
7612 vec3_t ambientcolor;
7614 // set the color tint used for lights affecting this surface
7615 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7617 // q3bsp has no lightmap updates, so the lightstylevalue that
7618 // would normally be baked into the lightmap must be
7619 // applied to the color
7620 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7621 if (model->type == mod_brushq3)
7622 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7623 colorscale *= r_refdef.lightmapintensity;
7624 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7625 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7626 // basic lit geometry
7627 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]);
7628 // add pants/shirt if needed
7629 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7630 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]);
7631 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7632 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]);
7633 // now add ambient passes if needed
7634 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7636 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]);
7637 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7638 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]);
7639 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7640 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]);
7643 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7644 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]);
7645 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7647 // if this is opaque use alpha blend which will darken the earlier
7650 // if this is an alpha blended material, all the earlier passes
7651 // were darkened by fog already, so we only need to add the fog
7652 // color ontop through the fog mask texture
7654 // if this is an additive blended material, all the earlier passes
7655 // were darkened by fog already, and we should not add fog color
7656 // (because the background was not darkened, there is no fog color
7657 // that was lost behind it).
7658 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]);
7662 return t->currentframe;
7665 rsurfacestate_t rsurface;
7667 void RSurf_ActiveWorldEntity(void)
7669 dp_model_t *model = r_refdef.scene.worldmodel;
7670 //if (rsurface.entity == r_refdef.scene.worldentity)
7672 rsurface.entity = r_refdef.scene.worldentity;
7673 rsurface.skeleton = NULL;
7674 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7675 rsurface.ent_skinnum = 0;
7676 rsurface.ent_qwskin = -1;
7677 rsurface.ent_shadertime = 0;
7678 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7679 rsurface.matrix = identitymatrix;
7680 rsurface.inversematrix = identitymatrix;
7681 rsurface.matrixscale = 1;
7682 rsurface.inversematrixscale = 1;
7683 R_EntityMatrix(&identitymatrix);
7684 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7685 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7686 rsurface.fograngerecip = r_refdef.fograngerecip;
7687 rsurface.fogheightfade = r_refdef.fogheightfade;
7688 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7689 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7690 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7691 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7692 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7693 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7694 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7695 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7696 rsurface.colormod[3] = 1;
7697 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);
7698 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7699 rsurface.frameblend[0].lerp = 1;
7700 rsurface.ent_alttextures = false;
7701 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7702 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7703 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7704 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7705 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7706 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7707 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7708 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7709 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7710 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7711 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7712 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7713 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7714 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7715 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7716 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7717 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7718 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7719 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7720 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7721 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7722 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7723 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7724 rsurface.modelelement3i = model->surfmesh.data_element3i;
7725 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7726 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7727 rsurface.modelelement3s = model->surfmesh.data_element3s;
7728 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7729 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7730 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7731 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7732 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7733 rsurface.modelsurfaces = model->data_surfaces;
7734 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7735 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7736 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7737 rsurface.modelgeneratedvertex = false;
7738 rsurface.batchgeneratedvertex = false;
7739 rsurface.batchfirstvertex = 0;
7740 rsurface.batchnumvertices = 0;
7741 rsurface.batchfirsttriangle = 0;
7742 rsurface.batchnumtriangles = 0;
7743 rsurface.batchvertex3f = NULL;
7744 rsurface.batchvertex3f_vertexbuffer = NULL;
7745 rsurface.batchvertex3f_bufferoffset = 0;
7746 rsurface.batchsvector3f = NULL;
7747 rsurface.batchsvector3f_vertexbuffer = NULL;
7748 rsurface.batchsvector3f_bufferoffset = 0;
7749 rsurface.batchtvector3f = NULL;
7750 rsurface.batchtvector3f_vertexbuffer = NULL;
7751 rsurface.batchtvector3f_bufferoffset = 0;
7752 rsurface.batchnormal3f = NULL;
7753 rsurface.batchnormal3f_vertexbuffer = NULL;
7754 rsurface.batchnormal3f_bufferoffset = 0;
7755 rsurface.batchlightmapcolor4f = NULL;
7756 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7757 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7758 rsurface.batchtexcoordtexture2f = NULL;
7759 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7760 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7761 rsurface.batchtexcoordlightmap2f = NULL;
7762 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7763 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7764 rsurface.batchvertexmesh = NULL;
7765 rsurface.batchvertexmeshbuffer = NULL;
7766 rsurface.batchvertex3fbuffer = NULL;
7767 rsurface.batchelement3i = NULL;
7768 rsurface.batchelement3i_indexbuffer = NULL;
7769 rsurface.batchelement3i_bufferoffset = 0;
7770 rsurface.batchelement3s = NULL;
7771 rsurface.batchelement3s_indexbuffer = NULL;
7772 rsurface.batchelement3s_bufferoffset = 0;
7773 rsurface.passcolor4f = NULL;
7774 rsurface.passcolor4f_vertexbuffer = NULL;
7775 rsurface.passcolor4f_bufferoffset = 0;
7778 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7780 dp_model_t *model = ent->model;
7781 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7783 rsurface.entity = (entity_render_t *)ent;
7784 rsurface.skeleton = ent->skeleton;
7785 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7786 rsurface.ent_skinnum = ent->skinnum;
7787 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;
7788 rsurface.ent_shadertime = ent->shadertime;
7789 rsurface.ent_flags = ent->flags;
7790 rsurface.matrix = ent->matrix;
7791 rsurface.inversematrix = ent->inversematrix;
7792 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7793 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7794 R_EntityMatrix(&rsurface.matrix);
7795 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7796 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7797 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7798 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7799 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7800 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7801 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7802 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7803 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7804 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7805 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7806 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7807 rsurface.colormod[3] = ent->alpha;
7808 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7809 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7810 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7811 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7812 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7813 if (ent->model->brush.submodel && !prepass)
7815 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7816 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7818 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7820 if (ent->animcache_vertex3f)
7822 rsurface.modelvertex3f = ent->animcache_vertex3f;
7823 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7824 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7825 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7826 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7827 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7828 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7830 else if (wanttangents)
7832 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7833 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7834 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7835 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7836 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7837 rsurface.modelvertexmesh = NULL;
7838 rsurface.modelvertexmeshbuffer = NULL;
7839 rsurface.modelvertex3fbuffer = NULL;
7841 else if (wantnormals)
7843 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7844 rsurface.modelsvector3f = NULL;
7845 rsurface.modeltvector3f = NULL;
7846 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7847 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7848 rsurface.modelvertexmesh = NULL;
7849 rsurface.modelvertexmeshbuffer = NULL;
7850 rsurface.modelvertex3fbuffer = NULL;
7854 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7855 rsurface.modelsvector3f = NULL;
7856 rsurface.modeltvector3f = NULL;
7857 rsurface.modelnormal3f = NULL;
7858 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7859 rsurface.modelvertexmesh = NULL;
7860 rsurface.modelvertexmeshbuffer = NULL;
7861 rsurface.modelvertex3fbuffer = NULL;
7863 rsurface.modelvertex3f_vertexbuffer = 0;
7864 rsurface.modelvertex3f_bufferoffset = 0;
7865 rsurface.modelsvector3f_vertexbuffer = 0;
7866 rsurface.modelsvector3f_bufferoffset = 0;
7867 rsurface.modeltvector3f_vertexbuffer = 0;
7868 rsurface.modeltvector3f_bufferoffset = 0;
7869 rsurface.modelnormal3f_vertexbuffer = 0;
7870 rsurface.modelnormal3f_bufferoffset = 0;
7871 rsurface.modelgeneratedvertex = true;
7875 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7876 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7877 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7878 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7879 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7880 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7881 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7882 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7883 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7884 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7885 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7886 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7887 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7888 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7889 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7890 rsurface.modelgeneratedvertex = false;
7892 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7893 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7894 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7895 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7896 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7897 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7898 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7899 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7900 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7901 rsurface.modelelement3i = model->surfmesh.data_element3i;
7902 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7903 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7904 rsurface.modelelement3s = model->surfmesh.data_element3s;
7905 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7906 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7907 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7908 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7909 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7910 rsurface.modelsurfaces = model->data_surfaces;
7911 rsurface.batchgeneratedvertex = false;
7912 rsurface.batchfirstvertex = 0;
7913 rsurface.batchnumvertices = 0;
7914 rsurface.batchfirsttriangle = 0;
7915 rsurface.batchnumtriangles = 0;
7916 rsurface.batchvertex3f = NULL;
7917 rsurface.batchvertex3f_vertexbuffer = NULL;
7918 rsurface.batchvertex3f_bufferoffset = 0;
7919 rsurface.batchsvector3f = NULL;
7920 rsurface.batchsvector3f_vertexbuffer = NULL;
7921 rsurface.batchsvector3f_bufferoffset = 0;
7922 rsurface.batchtvector3f = NULL;
7923 rsurface.batchtvector3f_vertexbuffer = NULL;
7924 rsurface.batchtvector3f_bufferoffset = 0;
7925 rsurface.batchnormal3f = NULL;
7926 rsurface.batchnormal3f_vertexbuffer = NULL;
7927 rsurface.batchnormal3f_bufferoffset = 0;
7928 rsurface.batchlightmapcolor4f = NULL;
7929 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7930 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7931 rsurface.batchtexcoordtexture2f = NULL;
7932 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7933 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7934 rsurface.batchtexcoordlightmap2f = NULL;
7935 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7936 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7937 rsurface.batchvertexmesh = NULL;
7938 rsurface.batchvertexmeshbuffer = NULL;
7939 rsurface.batchvertex3fbuffer = NULL;
7940 rsurface.batchelement3i = NULL;
7941 rsurface.batchelement3i_indexbuffer = NULL;
7942 rsurface.batchelement3i_bufferoffset = 0;
7943 rsurface.batchelement3s = NULL;
7944 rsurface.batchelement3s_indexbuffer = NULL;
7945 rsurface.batchelement3s_bufferoffset = 0;
7946 rsurface.passcolor4f = NULL;
7947 rsurface.passcolor4f_vertexbuffer = NULL;
7948 rsurface.passcolor4f_bufferoffset = 0;
7951 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)
7953 rsurface.entity = r_refdef.scene.worldentity;
7954 rsurface.skeleton = NULL;
7955 rsurface.ent_skinnum = 0;
7956 rsurface.ent_qwskin = -1;
7957 rsurface.ent_shadertime = shadertime;
7958 rsurface.ent_flags = entflags;
7959 rsurface.modelnumvertices = numvertices;
7960 rsurface.modelnumtriangles = numtriangles;
7961 rsurface.matrix = *matrix;
7962 rsurface.inversematrix = *inversematrix;
7963 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7964 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7965 R_EntityMatrix(&rsurface.matrix);
7966 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7967 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7968 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7969 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7970 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7971 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7972 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7973 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7974 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7975 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7976 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7977 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7978 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);
7979 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7980 rsurface.frameblend[0].lerp = 1;
7981 rsurface.ent_alttextures = false;
7982 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7983 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7986 rsurface.modelvertex3f = (float *)vertex3f;
7987 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7988 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7989 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7991 else if (wantnormals)
7993 rsurface.modelvertex3f = (float *)vertex3f;
7994 rsurface.modelsvector3f = NULL;
7995 rsurface.modeltvector3f = NULL;
7996 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8000 rsurface.modelvertex3f = (float *)vertex3f;
8001 rsurface.modelsvector3f = NULL;
8002 rsurface.modeltvector3f = NULL;
8003 rsurface.modelnormal3f = NULL;
8005 rsurface.modelvertexmesh = NULL;
8006 rsurface.modelvertexmeshbuffer = NULL;
8007 rsurface.modelvertex3fbuffer = NULL;
8008 rsurface.modelvertex3f_vertexbuffer = 0;
8009 rsurface.modelvertex3f_bufferoffset = 0;
8010 rsurface.modelsvector3f_vertexbuffer = 0;
8011 rsurface.modelsvector3f_bufferoffset = 0;
8012 rsurface.modeltvector3f_vertexbuffer = 0;
8013 rsurface.modeltvector3f_bufferoffset = 0;
8014 rsurface.modelnormal3f_vertexbuffer = 0;
8015 rsurface.modelnormal3f_bufferoffset = 0;
8016 rsurface.modelgeneratedvertex = true;
8017 rsurface.modellightmapcolor4f = (float *)color4f;
8018 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8019 rsurface.modellightmapcolor4f_bufferoffset = 0;
8020 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8021 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8022 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8023 rsurface.modeltexcoordlightmap2f = NULL;
8024 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8025 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8026 rsurface.modelelement3i = (int *)element3i;
8027 rsurface.modelelement3i_indexbuffer = NULL;
8028 rsurface.modelelement3i_bufferoffset = 0;
8029 rsurface.modelelement3s = (unsigned short *)element3s;
8030 rsurface.modelelement3s_indexbuffer = NULL;
8031 rsurface.modelelement3s_bufferoffset = 0;
8032 rsurface.modellightmapoffsets = NULL;
8033 rsurface.modelsurfaces = NULL;
8034 rsurface.batchgeneratedvertex = false;
8035 rsurface.batchfirstvertex = 0;
8036 rsurface.batchnumvertices = 0;
8037 rsurface.batchfirsttriangle = 0;
8038 rsurface.batchnumtriangles = 0;
8039 rsurface.batchvertex3f = NULL;
8040 rsurface.batchvertex3f_vertexbuffer = NULL;
8041 rsurface.batchvertex3f_bufferoffset = 0;
8042 rsurface.batchsvector3f = NULL;
8043 rsurface.batchsvector3f_vertexbuffer = NULL;
8044 rsurface.batchsvector3f_bufferoffset = 0;
8045 rsurface.batchtvector3f = NULL;
8046 rsurface.batchtvector3f_vertexbuffer = NULL;
8047 rsurface.batchtvector3f_bufferoffset = 0;
8048 rsurface.batchnormal3f = NULL;
8049 rsurface.batchnormal3f_vertexbuffer = NULL;
8050 rsurface.batchnormal3f_bufferoffset = 0;
8051 rsurface.batchlightmapcolor4f = NULL;
8052 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8053 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8054 rsurface.batchtexcoordtexture2f = NULL;
8055 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8056 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8057 rsurface.batchtexcoordlightmap2f = NULL;
8058 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8059 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8060 rsurface.batchvertexmesh = NULL;
8061 rsurface.batchvertexmeshbuffer = NULL;
8062 rsurface.batchvertex3fbuffer = NULL;
8063 rsurface.batchelement3i = NULL;
8064 rsurface.batchelement3i_indexbuffer = NULL;
8065 rsurface.batchelement3i_bufferoffset = 0;
8066 rsurface.batchelement3s = NULL;
8067 rsurface.batchelement3s_indexbuffer = NULL;
8068 rsurface.batchelement3s_bufferoffset = 0;
8069 rsurface.passcolor4f = NULL;
8070 rsurface.passcolor4f_vertexbuffer = NULL;
8071 rsurface.passcolor4f_bufferoffset = 0;
8073 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8075 if ((wantnormals || wanttangents) && !normal3f)
8077 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8078 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8080 if (wanttangents && !svector3f)
8082 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8083 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8084 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8089 float RSurf_FogPoint(const float *v)
8091 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8092 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8093 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8094 float FogHeightFade = r_refdef.fogheightfade;
8096 unsigned int fogmasktableindex;
8097 if (r_refdef.fogplaneviewabove)
8098 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8100 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8101 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8102 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8105 float RSurf_FogVertex(const float *v)
8107 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8108 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8109 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8110 float FogHeightFade = rsurface.fogheightfade;
8112 unsigned int fogmasktableindex;
8113 if (r_refdef.fogplaneviewabove)
8114 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8116 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8117 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8118 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8121 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8124 for (i = 0;i < numelements;i++)
8125 outelement3i[i] = inelement3i[i] + adjust;
8128 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8129 extern cvar_t gl_vbo;
8130 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8138 int surfacefirsttriangle;
8139 int surfacenumtriangles;
8140 int surfacefirstvertex;
8141 int surfaceendvertex;
8142 int surfacenumvertices;
8143 int batchnumvertices;
8144 int batchnumtriangles;
8148 qboolean dynamicvertex;
8152 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8154 q3shaderinfo_deform_t *deform;
8155 const msurface_t *surface, *firstsurface;
8156 r_vertexmesh_t *vertexmesh;
8157 if (!texturenumsurfaces)
8159 // find vertex range of this surface batch
8161 firstsurface = texturesurfacelist[0];
8162 firsttriangle = firstsurface->num_firsttriangle;
8163 batchnumvertices = 0;
8164 batchnumtriangles = 0;
8165 firstvertex = endvertex = firstsurface->num_firstvertex;
8166 for (i = 0;i < texturenumsurfaces;i++)
8168 surface = texturesurfacelist[i];
8169 if (surface != firstsurface + i)
8171 surfacefirstvertex = surface->num_firstvertex;
8172 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8173 surfacenumvertices = surface->num_vertices;
8174 surfacenumtriangles = surface->num_triangles;
8175 if (firstvertex > surfacefirstvertex)
8176 firstvertex = surfacefirstvertex;
8177 if (endvertex < surfaceendvertex)
8178 endvertex = surfaceendvertex;
8179 batchnumvertices += surfacenumvertices;
8180 batchnumtriangles += surfacenumtriangles;
8183 // we now know the vertex range used, and if there are any gaps in it
8184 rsurface.batchfirstvertex = firstvertex;
8185 rsurface.batchnumvertices = endvertex - firstvertex;
8186 rsurface.batchfirsttriangle = firsttriangle;
8187 rsurface.batchnumtriangles = batchnumtriangles;
8189 // this variable holds flags for which properties have been updated that
8190 // may require regenerating vertexmesh array...
8193 // check if any dynamic vertex processing must occur
8194 dynamicvertex = false;
8196 // if there is a chance of animated vertex colors, it's a dynamic batch
8197 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8199 dynamicvertex = true;
8200 batchneed |= BATCHNEED_NOGAPS;
8201 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8204 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8206 switch (deform->deform)
8209 case Q3DEFORM_PROJECTIONSHADOW:
8210 case Q3DEFORM_TEXT0:
8211 case Q3DEFORM_TEXT1:
8212 case Q3DEFORM_TEXT2:
8213 case Q3DEFORM_TEXT3:
8214 case Q3DEFORM_TEXT4:
8215 case Q3DEFORM_TEXT5:
8216 case Q3DEFORM_TEXT6:
8217 case Q3DEFORM_TEXT7:
8220 case Q3DEFORM_AUTOSPRITE:
8221 dynamicvertex = true;
8222 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8223 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8225 case Q3DEFORM_AUTOSPRITE2:
8226 dynamicvertex = true;
8227 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8228 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8230 case Q3DEFORM_NORMAL:
8231 dynamicvertex = true;
8232 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8233 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8236 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8237 break; // if wavefunc is a nop, ignore this transform
8238 dynamicvertex = true;
8239 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8240 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8242 case Q3DEFORM_BULGE:
8243 dynamicvertex = true;
8244 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8245 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8248 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8249 break; // if wavefunc is a nop, ignore this transform
8250 dynamicvertex = true;
8251 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8252 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8256 switch(rsurface.texture->tcgen.tcgen)
8259 case Q3TCGEN_TEXTURE:
8261 case Q3TCGEN_LIGHTMAP:
8262 dynamicvertex = true;
8263 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8264 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8266 case Q3TCGEN_VECTOR:
8267 dynamicvertex = true;
8268 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8269 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8271 case Q3TCGEN_ENVIRONMENT:
8272 dynamicvertex = true;
8273 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8274 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8277 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8279 dynamicvertex = true;
8280 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8281 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8284 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8286 dynamicvertex = true;
8287 batchneed |= BATCHNEED_NOGAPS;
8288 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8291 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8293 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8294 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8295 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8296 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8297 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8298 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8299 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8302 // when the model data has no vertex buffer (dynamic mesh), we need to
8304 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8305 batchneed |= BATCHNEED_NOGAPS;
8307 // if needsupdate, we have to do a dynamic vertex batch for sure
8308 if (needsupdate & batchneed)
8309 dynamicvertex = true;
8311 // see if we need to build vertexmesh from arrays
8312 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8313 dynamicvertex = true;
8315 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8316 // also some drivers strongly dislike firstvertex
8317 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8318 dynamicvertex = true;
8320 rsurface.batchvertex3f = rsurface.modelvertex3f;
8321 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8322 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8323 rsurface.batchsvector3f = rsurface.modelsvector3f;
8324 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8325 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8326 rsurface.batchtvector3f = rsurface.modeltvector3f;
8327 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8328 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8329 rsurface.batchnormal3f = rsurface.modelnormal3f;
8330 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8331 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8332 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8333 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8334 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8335 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8336 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8337 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8338 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8339 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8340 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8341 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8342 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8343 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8344 rsurface.batchelement3i = rsurface.modelelement3i;
8345 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8346 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8347 rsurface.batchelement3s = rsurface.modelelement3s;
8348 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8349 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8351 // if any dynamic vertex processing has to occur in software, we copy the
8352 // entire surface list together before processing to rebase the vertices
8353 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8355 // if any gaps exist and we do not have a static vertex buffer, we have to
8356 // copy the surface list together to avoid wasting upload bandwidth on the
8357 // vertices in the gaps.
8359 // if gaps exist and we have a static vertex buffer, we still have to
8360 // combine the index buffer ranges into one dynamic index buffer.
8362 // in all cases we end up with data that can be drawn in one call.
8366 // static vertex data, just set pointers...
8367 rsurface.batchgeneratedvertex = false;
8368 // if there are gaps, we want to build a combined index buffer,
8369 // otherwise use the original static buffer with an appropriate offset
8372 // build a new triangle elements array for this batch
8373 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8374 rsurface.batchfirsttriangle = 0;
8376 for (i = 0;i < texturenumsurfaces;i++)
8378 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8379 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8380 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8381 numtriangles += surfacenumtriangles;
8383 rsurface.batchelement3i_indexbuffer = NULL;
8384 rsurface.batchelement3i_bufferoffset = 0;
8385 rsurface.batchelement3s = NULL;
8386 rsurface.batchelement3s_indexbuffer = NULL;
8387 rsurface.batchelement3s_bufferoffset = 0;
8388 if (endvertex <= 65536)
8390 // make a 16bit (unsigned short) index array if possible
8391 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8392 for (i = 0;i < numtriangles*3;i++)
8393 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8399 // something needs software processing, do it for real...
8400 // we only directly handle separate array data in this case and then
8401 // generate interleaved data if needed...
8402 rsurface.batchgeneratedvertex = true;
8404 // now copy the vertex data into a combined array and make an index array
8405 // (this is what Quake3 does all the time)
8406 //if (gaps || rsurface.batchfirstvertex)
8408 rsurface.batchvertex3fbuffer = NULL;
8409 rsurface.batchvertexmesh = NULL;
8410 rsurface.batchvertexmeshbuffer = NULL;
8411 rsurface.batchvertex3f = NULL;
8412 rsurface.batchvertex3f_vertexbuffer = NULL;
8413 rsurface.batchvertex3f_bufferoffset = 0;
8414 rsurface.batchsvector3f = NULL;
8415 rsurface.batchsvector3f_vertexbuffer = NULL;
8416 rsurface.batchsvector3f_bufferoffset = 0;
8417 rsurface.batchtvector3f = NULL;
8418 rsurface.batchtvector3f_vertexbuffer = NULL;
8419 rsurface.batchtvector3f_bufferoffset = 0;
8420 rsurface.batchnormal3f = NULL;
8421 rsurface.batchnormal3f_vertexbuffer = NULL;
8422 rsurface.batchnormal3f_bufferoffset = 0;
8423 rsurface.batchlightmapcolor4f = NULL;
8424 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8425 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8426 rsurface.batchtexcoordtexture2f = NULL;
8427 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8428 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8429 rsurface.batchtexcoordlightmap2f = NULL;
8430 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8431 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8432 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8433 rsurface.batchelement3i_indexbuffer = NULL;
8434 rsurface.batchelement3i_bufferoffset = 0;
8435 rsurface.batchelement3s = NULL;
8436 rsurface.batchelement3s_indexbuffer = NULL;
8437 rsurface.batchelement3s_bufferoffset = 0;
8438 // we'll only be setting up certain arrays as needed
8439 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8440 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8441 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8442 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8443 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8444 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8445 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8447 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8448 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8450 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8451 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8452 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8453 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8454 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8455 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8458 for (i = 0;i < texturenumsurfaces;i++)
8460 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8461 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8462 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8463 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8464 // copy only the data requested
8465 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8466 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8467 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8469 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8470 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8471 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8472 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8473 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8475 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8476 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8478 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8479 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8480 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8481 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8482 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8483 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8485 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8486 numvertices += surfacenumvertices;
8487 numtriangles += surfacenumtriangles;
8490 // generate a 16bit index array as well if possible
8491 // (in general, dynamic batches fit)
8492 if (numvertices <= 65536)
8494 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8495 for (i = 0;i < numtriangles*3;i++)
8496 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8499 // since we've copied everything, the batch now starts at 0
8500 rsurface.batchfirstvertex = 0;
8501 rsurface.batchnumvertices = batchnumvertices;
8502 rsurface.batchfirsttriangle = 0;
8503 rsurface.batchnumtriangles = batchnumtriangles;
8506 // q1bsp surfaces rendered in vertex color mode have to have colors
8507 // calculated based on lightstyles
8508 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8510 // generate color arrays for the surfaces in this list
8515 const unsigned char *lm;
8516 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8517 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8518 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8520 for (i = 0;i < texturenumsurfaces;i++)
8522 surface = texturesurfacelist[i];
8523 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8524 surfacenumvertices = surface->num_vertices;
8525 if (surface->lightmapinfo->samples)
8527 for (j = 0;j < surfacenumvertices;j++)
8529 lm = surface->lightmapinfo->samples + offsets[j];
8530 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8531 VectorScale(lm, scale, c);
8532 if (surface->lightmapinfo->styles[1] != 255)
8534 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8536 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8537 VectorMA(c, scale, lm, c);
8538 if (surface->lightmapinfo->styles[2] != 255)
8541 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8542 VectorMA(c, scale, lm, c);
8543 if (surface->lightmapinfo->styles[3] != 255)
8546 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8547 VectorMA(c, scale, lm, c);
8554 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);
8560 for (j = 0;j < surfacenumvertices;j++)
8562 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8569 // if vertices are deformed (sprite flares and things in maps, possibly
8570 // water waves, bulges and other deformations), modify the copied vertices
8572 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8574 switch (deform->deform)
8577 case Q3DEFORM_PROJECTIONSHADOW:
8578 case Q3DEFORM_TEXT0:
8579 case Q3DEFORM_TEXT1:
8580 case Q3DEFORM_TEXT2:
8581 case Q3DEFORM_TEXT3:
8582 case Q3DEFORM_TEXT4:
8583 case Q3DEFORM_TEXT5:
8584 case Q3DEFORM_TEXT6:
8585 case Q3DEFORM_TEXT7:
8588 case Q3DEFORM_AUTOSPRITE:
8589 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8590 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8591 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8592 VectorNormalize(newforward);
8593 VectorNormalize(newright);
8594 VectorNormalize(newup);
8595 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8596 // rsurface.batchvertex3f_vertexbuffer = NULL;
8597 // rsurface.batchvertex3f_bufferoffset = 0;
8598 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8599 // rsurface.batchsvector3f_vertexbuffer = NULL;
8600 // rsurface.batchsvector3f_bufferoffset = 0;
8601 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8602 // rsurface.batchtvector3f_vertexbuffer = NULL;
8603 // rsurface.batchtvector3f_bufferoffset = 0;
8604 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8605 // rsurface.batchnormal3f_vertexbuffer = NULL;
8606 // rsurface.batchnormal3f_bufferoffset = 0;
8607 // a single autosprite surface can contain multiple sprites...
8608 for (j = 0;j < batchnumvertices - 3;j += 4)
8610 VectorClear(center);
8611 for (i = 0;i < 4;i++)
8612 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8613 VectorScale(center, 0.25f, center);
8614 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8615 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8616 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8617 for (i = 0;i < 4;i++)
8619 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8620 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8623 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8624 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8625 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);
8627 case Q3DEFORM_AUTOSPRITE2:
8628 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8629 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8630 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8631 VectorNormalize(newforward);
8632 VectorNormalize(newright);
8633 VectorNormalize(newup);
8634 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8635 // rsurface.batchvertex3f_vertexbuffer = NULL;
8636 // rsurface.batchvertex3f_bufferoffset = 0;
8638 const float *v1, *v2;
8648 memset(shortest, 0, sizeof(shortest));
8649 // a single autosprite surface can contain multiple sprites...
8650 for (j = 0;j < batchnumvertices - 3;j += 4)
8652 VectorClear(center);
8653 for (i = 0;i < 4;i++)
8654 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8655 VectorScale(center, 0.25f, center);
8656 // find the two shortest edges, then use them to define the
8657 // axis vectors for rotating around the central axis
8658 for (i = 0;i < 6;i++)
8660 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8661 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8662 l = VectorDistance2(v1, v2);
8663 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8665 l += (1.0f / 1024.0f);
8666 if (shortest[0].length2 > l || i == 0)
8668 shortest[1] = shortest[0];
8669 shortest[0].length2 = l;
8670 shortest[0].v1 = v1;
8671 shortest[0].v2 = v2;
8673 else if (shortest[1].length2 > l || i == 1)
8675 shortest[1].length2 = l;
8676 shortest[1].v1 = v1;
8677 shortest[1].v2 = v2;
8680 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8681 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8682 // this calculates the right vector from the shortest edge
8683 // and the up vector from the edge midpoints
8684 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8685 VectorNormalize(right);
8686 VectorSubtract(end, start, up);
8687 VectorNormalize(up);
8688 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8689 VectorSubtract(rsurface.localvieworigin, center, forward);
8690 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8691 VectorNegate(forward, forward);
8692 VectorReflect(forward, 0, up, forward);
8693 VectorNormalize(forward);
8694 CrossProduct(up, forward, newright);
8695 VectorNormalize(newright);
8696 // rotate the quad around the up axis vector, this is made
8697 // especially easy by the fact we know the quad is flat,
8698 // so we only have to subtract the center position and
8699 // measure distance along the right vector, and then
8700 // multiply that by the newright vector and add back the
8702 // we also need to subtract the old position to undo the
8703 // displacement from the center, which we do with a
8704 // DotProduct, the subtraction/addition of center is also
8705 // optimized into DotProducts here
8706 l = DotProduct(right, center);
8707 for (i = 0;i < 4;i++)
8709 v1 = rsurface.batchvertex3f + 3*(j+i);
8710 f = DotProduct(right, v1) - l;
8711 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8715 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8717 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8718 // rsurface.batchnormal3f_vertexbuffer = NULL;
8719 // rsurface.batchnormal3f_bufferoffset = 0;
8720 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8722 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8724 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8725 // rsurface.batchsvector3f_vertexbuffer = NULL;
8726 // rsurface.batchsvector3f_bufferoffset = 0;
8727 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8728 // rsurface.batchtvector3f_vertexbuffer = NULL;
8729 // rsurface.batchtvector3f_bufferoffset = 0;
8730 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);
8733 case Q3DEFORM_NORMAL:
8734 // deform the normals to make reflections wavey
8735 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8736 rsurface.batchnormal3f_vertexbuffer = NULL;
8737 rsurface.batchnormal3f_bufferoffset = 0;
8738 for (j = 0;j < batchnumvertices;j++)
8741 float *normal = rsurface.batchnormal3f + 3*j;
8742 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8743 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8744 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]);
8745 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]);
8746 VectorNormalize(normal);
8748 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8750 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8751 // rsurface.batchsvector3f_vertexbuffer = NULL;
8752 // rsurface.batchsvector3f_bufferoffset = 0;
8753 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8754 // rsurface.batchtvector3f_vertexbuffer = NULL;
8755 // rsurface.batchtvector3f_bufferoffset = 0;
8756 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);
8760 // deform vertex array to make wavey water and flags and such
8761 waveparms[0] = deform->waveparms[0];
8762 waveparms[1] = deform->waveparms[1];
8763 waveparms[2] = deform->waveparms[2];
8764 waveparms[3] = deform->waveparms[3];
8765 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8766 break; // if wavefunc is a nop, don't make a dynamic vertex array
8767 // this is how a divisor of vertex influence on deformation
8768 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8769 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8770 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8771 // rsurface.batchvertex3f_vertexbuffer = NULL;
8772 // rsurface.batchvertex3f_bufferoffset = 0;
8773 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8774 // rsurface.batchnormal3f_vertexbuffer = NULL;
8775 // rsurface.batchnormal3f_bufferoffset = 0;
8776 for (j = 0;j < batchnumvertices;j++)
8778 // if the wavefunc depends on time, evaluate it per-vertex
8781 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8782 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8784 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8786 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8787 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8788 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8790 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8791 // rsurface.batchsvector3f_vertexbuffer = NULL;
8792 // rsurface.batchsvector3f_bufferoffset = 0;
8793 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794 // rsurface.batchtvector3f_vertexbuffer = NULL;
8795 // rsurface.batchtvector3f_bufferoffset = 0;
8796 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);
8799 case Q3DEFORM_BULGE:
8800 // deform vertex array to make the surface have moving bulges
8801 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8802 // rsurface.batchvertex3f_vertexbuffer = NULL;
8803 // rsurface.batchvertex3f_bufferoffset = 0;
8804 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8805 // rsurface.batchnormal3f_vertexbuffer = NULL;
8806 // rsurface.batchnormal3f_bufferoffset = 0;
8807 for (j = 0;j < batchnumvertices;j++)
8809 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8810 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8812 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8813 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8814 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8816 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8817 // rsurface.batchsvector3f_vertexbuffer = NULL;
8818 // rsurface.batchsvector3f_bufferoffset = 0;
8819 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820 // rsurface.batchtvector3f_vertexbuffer = NULL;
8821 // rsurface.batchtvector3f_bufferoffset = 0;
8822 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);
8826 // deform vertex array
8827 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8828 break; // if wavefunc is a nop, don't make a dynamic vertex array
8829 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8830 VectorScale(deform->parms, scale, waveparms);
8831 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8832 // rsurface.batchvertex3f_vertexbuffer = NULL;
8833 // rsurface.batchvertex3f_bufferoffset = 0;
8834 for (j = 0;j < batchnumvertices;j++)
8835 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8840 // generate texcoords based on the chosen texcoord source
8841 switch(rsurface.texture->tcgen.tcgen)
8844 case Q3TCGEN_TEXTURE:
8846 case Q3TCGEN_LIGHTMAP:
8847 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8848 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8849 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8850 if (rsurface.batchtexcoordlightmap2f)
8851 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8853 case Q3TCGEN_VECTOR:
8854 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8855 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8856 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8857 for (j = 0;j < batchnumvertices;j++)
8859 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8860 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8863 case Q3TCGEN_ENVIRONMENT:
8864 // make environment reflections using a spheremap
8865 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8866 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8867 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8868 for (j = 0;j < batchnumvertices;j++)
8870 // identical to Q3A's method, but executed in worldspace so
8871 // carried models can be shiny too
8873 float viewer[3], d, reflected[3], worldreflected[3];
8875 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8876 // VectorNormalize(viewer);
8878 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8880 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8881 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8882 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8883 // note: this is proportinal to viewer, so we can normalize later
8885 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8886 VectorNormalize(worldreflected);
8888 // note: this sphere map only uses world x and z!
8889 // so positive and negative y will LOOK THE SAME.
8890 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8891 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8895 // the only tcmod that needs software vertex processing is turbulent, so
8896 // check for it here and apply the changes if needed
8897 // and we only support that as the first one
8898 // (handling a mixture of turbulent and other tcmods would be problematic
8899 // without punting it entirely to a software path)
8900 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8902 amplitude = rsurface.texture->tcmods[0].parms[1];
8903 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8904 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8905 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8906 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8907 for (j = 0;j < batchnumvertices;j++)
8909 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);
8910 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8914 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8916 // convert the modified arrays to vertex structs
8917 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8918 // rsurface.batchvertexmeshbuffer = NULL;
8919 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8920 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8921 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8922 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8923 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8924 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8925 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8927 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8929 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8930 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8933 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8934 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8935 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8936 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8937 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8938 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8939 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8940 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8941 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8945 void RSurf_DrawBatch(void)
8947 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8948 // through the pipeline, killing it earlier in the pipeline would have
8949 // per-surface overhead rather than per-batch overhead, so it's best to
8950 // reject it here, before it hits glDraw.
8951 if (rsurface.batchnumtriangles == 0)
8954 // batch debugging code
8955 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8961 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8962 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8965 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8967 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8969 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8970 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);
8977 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);
8980 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8982 // pick the closest matching water plane
8983 int planeindex, vertexindex, bestplaneindex = -1;
8987 r_waterstate_waterplane_t *p;
8988 qboolean prepared = false;
8990 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8992 if(p->camera_entity != rsurface.texture->camera_entity)
8997 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8999 if(rsurface.batchnumvertices == 0)
9002 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9004 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9005 d += fabs(PlaneDiff(vert, &p->plane));
9007 if (bestd > d || bestplaneindex < 0)
9010 bestplaneindex = planeindex;
9013 return bestplaneindex;
9014 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9015 // this situation though, as it might be better to render single larger
9016 // batches with useless stuff (backface culled for example) than to
9017 // render multiple smaller batches
9020 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9023 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9024 rsurface.passcolor4f_vertexbuffer = 0;
9025 rsurface.passcolor4f_bufferoffset = 0;
9026 for (i = 0;i < rsurface.batchnumvertices;i++)
9027 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9030 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9037 if (rsurface.passcolor4f)
9039 // generate color arrays
9040 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9041 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9042 rsurface.passcolor4f_vertexbuffer = 0;
9043 rsurface.passcolor4f_bufferoffset = 0;
9044 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)
9046 f = RSurf_FogVertex(v);
9055 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9056 rsurface.passcolor4f_vertexbuffer = 0;
9057 rsurface.passcolor4f_bufferoffset = 0;
9058 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9060 f = RSurf_FogVertex(v);
9069 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9076 if (!rsurface.passcolor4f)
9078 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9079 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9080 rsurface.passcolor4f_vertexbuffer = 0;
9081 rsurface.passcolor4f_bufferoffset = 0;
9082 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)
9084 f = RSurf_FogVertex(v);
9085 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9086 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9087 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9092 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9097 if (!rsurface.passcolor4f)
9099 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9100 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9101 rsurface.passcolor4f_vertexbuffer = 0;
9102 rsurface.passcolor4f_bufferoffset = 0;
9103 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9112 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9117 if (!rsurface.passcolor4f)
9119 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9120 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9121 rsurface.passcolor4f_vertexbuffer = 0;
9122 rsurface.passcolor4f_bufferoffset = 0;
9123 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9125 c2[0] = c[0] + r_refdef.scene.ambient;
9126 c2[1] = c[1] + r_refdef.scene.ambient;
9127 c2[2] = c[2] + r_refdef.scene.ambient;
9132 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9135 rsurface.passcolor4f = NULL;
9136 rsurface.passcolor4f_vertexbuffer = 0;
9137 rsurface.passcolor4f_bufferoffset = 0;
9138 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9139 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9140 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9141 GL_Color(r, g, b, a);
9142 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9146 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9148 // TODO: optimize applyfog && applycolor case
9149 // just apply fog if necessary, and tint the fog color array if necessary
9150 rsurface.passcolor4f = NULL;
9151 rsurface.passcolor4f_vertexbuffer = 0;
9152 rsurface.passcolor4f_bufferoffset = 0;
9153 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9154 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9155 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9156 GL_Color(r, g, b, a);
9160 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9163 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9164 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9165 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9166 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9167 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9168 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9169 GL_Color(r, g, b, a);
9173 static void RSurf_DrawBatch_GL11_ClampColor(void)
9178 if (!rsurface.passcolor4f)
9180 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9182 c2[0] = bound(0.0f, c1[0], 1.0f);
9183 c2[1] = bound(0.0f, c1[1], 1.0f);
9184 c2[2] = bound(0.0f, c1[2], 1.0f);
9185 c2[3] = bound(0.0f, c1[3], 1.0f);
9189 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9199 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9200 rsurface.passcolor4f_vertexbuffer = 0;
9201 rsurface.passcolor4f_bufferoffset = 0;
9202 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)
9204 f = -DotProduct(r_refdef.view.forward, n);
9206 f = f * 0.85 + 0.15; // work around so stuff won't get black
9207 f *= r_refdef.lightmapintensity;
9208 Vector4Set(c, f, f, f, 1);
9212 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9214 RSurf_DrawBatch_GL11_ApplyFakeLight();
9215 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9216 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9217 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9218 GL_Color(r, g, b, a);
9222 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9230 vec3_t ambientcolor;
9231 vec3_t diffusecolor;
9235 VectorCopy(rsurface.modellight_lightdir, lightdir);
9236 f = 0.5f * r_refdef.lightmapintensity;
9237 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9238 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9239 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9240 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9241 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9242 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9244 if (VectorLength2(diffusecolor) > 0)
9246 // q3-style directional shading
9247 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9248 rsurface.passcolor4f_vertexbuffer = 0;
9249 rsurface.passcolor4f_bufferoffset = 0;
9250 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)
9252 if ((f = DotProduct(n, lightdir)) > 0)
9253 VectorMA(ambientcolor, f, diffusecolor, c);
9255 VectorCopy(ambientcolor, c);
9262 *applycolor = false;
9266 *r = ambientcolor[0];
9267 *g = ambientcolor[1];
9268 *b = ambientcolor[2];
9269 rsurface.passcolor4f = NULL;
9270 rsurface.passcolor4f_vertexbuffer = 0;
9271 rsurface.passcolor4f_bufferoffset = 0;
9275 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9277 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9278 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9279 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9280 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9281 GL_Color(r, g, b, a);
9285 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9293 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9294 rsurface.passcolor4f_vertexbuffer = 0;
9295 rsurface.passcolor4f_bufferoffset = 0;
9297 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9299 f = 1 - RSurf_FogVertex(v);
9307 void RSurf_SetupDepthAndCulling(void)
9309 // submodels are biased to avoid z-fighting with world surfaces that they
9310 // may be exactly overlapping (avoids z-fighting artifacts on certain
9311 // doors and things in Quake maps)
9312 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9313 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9314 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9315 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9318 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9320 // transparent sky would be ridiculous
9321 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9323 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9324 skyrenderlater = true;
9325 RSurf_SetupDepthAndCulling();
9327 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9328 // skymasking on them, and Quake3 never did sky masking (unlike
9329 // software Quake and software Quake2), so disable the sky masking
9330 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9331 // and skymasking also looks very bad when noclipping outside the
9332 // level, so don't use it then either.
9333 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9335 R_Mesh_ResetTextureState();
9336 if (skyrendermasked)
9338 R_SetupShader_DepthOrShadow();
9339 // depth-only (masking)
9340 GL_ColorMask(0,0,0,0);
9341 // just to make sure that braindead drivers don't draw
9342 // anything despite that colormask...
9343 GL_BlendFunc(GL_ZERO, GL_ONE);
9344 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9345 if (rsurface.batchvertex3fbuffer)
9346 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9348 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9352 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9354 GL_BlendFunc(GL_ONE, GL_ZERO);
9355 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9356 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9357 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9360 if (skyrendermasked)
9361 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9363 R_Mesh_ResetTextureState();
9364 GL_Color(1, 1, 1, 1);
9367 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9368 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9369 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9371 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9375 // render screenspace normalmap to texture
9377 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9382 // bind lightmap texture
9384 // water/refraction/reflection/camera surfaces have to be handled specially
9385 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9387 int start, end, startplaneindex;
9388 for (start = 0;start < texturenumsurfaces;start = end)
9390 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9391 if(startplaneindex < 0)
9393 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9394 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9398 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9400 // now that we have a batch using the same planeindex, render it
9401 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9403 // render water or distortion background
9405 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));
9407 // blend surface on top
9408 GL_DepthMask(false);
9409 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9412 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9414 // render surface with reflection texture as input
9415 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9416 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));
9423 // render surface batch normally
9424 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9425 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9429 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9431 // OpenGL 1.3 path - anything not completely ancient
9432 qboolean applycolor;
9435 const texturelayer_t *layer;
9436 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);
9437 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9439 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9442 int layertexrgbscale;
9443 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9445 if (layerindex == 0)
9449 GL_AlphaTest(false);
9450 GL_DepthFunc(GL_EQUAL);
9453 GL_DepthMask(layer->depthmask && writedepth);
9454 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9455 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9457 layertexrgbscale = 4;
9458 VectorScale(layer->color, 0.25f, layercolor);
9460 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9462 layertexrgbscale = 2;
9463 VectorScale(layer->color, 0.5f, layercolor);
9467 layertexrgbscale = 1;
9468 VectorScale(layer->color, 1.0f, layercolor);
9470 layercolor[3] = layer->color[3];
9471 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9472 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9473 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9474 switch (layer->type)
9476 case TEXTURELAYERTYPE_LITTEXTURE:
9477 // single-pass lightmapped texture with 2x rgbscale
9478 R_Mesh_TexBind(0, r_texture_white);
9479 R_Mesh_TexMatrix(0, NULL);
9480 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9481 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9482 R_Mesh_TexBind(1, layer->texture);
9483 R_Mesh_TexMatrix(1, &layer->texmatrix);
9484 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9485 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9486 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9487 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9488 else if (FAKELIGHT_ENABLED)
9489 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9490 else if (rsurface.uselightmaptexture)
9491 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9493 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9495 case TEXTURELAYERTYPE_TEXTURE:
9496 // singletexture unlit texture with transparency support
9497 R_Mesh_TexBind(0, layer->texture);
9498 R_Mesh_TexMatrix(0, &layer->texmatrix);
9499 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9500 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9501 R_Mesh_TexBind(1, 0);
9502 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9503 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9505 case TEXTURELAYERTYPE_FOG:
9506 // singletexture fogging
9509 R_Mesh_TexBind(0, layer->texture);
9510 R_Mesh_TexMatrix(0, &layer->texmatrix);
9511 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9512 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9516 R_Mesh_TexBind(0, 0);
9517 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9519 R_Mesh_TexBind(1, 0);
9520 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9521 // generate a color array for the fog pass
9522 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9523 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9527 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9530 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9532 GL_DepthFunc(GL_LEQUAL);
9533 GL_AlphaTest(false);
9537 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9539 // OpenGL 1.1 - crusty old voodoo path
9542 const texturelayer_t *layer;
9543 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);
9544 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9546 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9548 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9550 if (layerindex == 0)
9554 GL_AlphaTest(false);
9555 GL_DepthFunc(GL_EQUAL);
9558 GL_DepthMask(layer->depthmask && writedepth);
9559 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9560 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9561 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9562 switch (layer->type)
9564 case TEXTURELAYERTYPE_LITTEXTURE:
9565 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9567 // two-pass lit texture with 2x rgbscale
9568 // first the lightmap pass
9569 R_Mesh_TexBind(0, r_texture_white);
9570 R_Mesh_TexMatrix(0, NULL);
9571 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9572 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9573 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9574 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9575 else if (FAKELIGHT_ENABLED)
9576 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9577 else if (rsurface.uselightmaptexture)
9578 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9580 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9581 // then apply the texture to it
9582 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9583 R_Mesh_TexBind(0, layer->texture);
9584 R_Mesh_TexMatrix(0, &layer->texmatrix);
9585 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9586 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9587 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);
9591 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9592 R_Mesh_TexBind(0, layer->texture);
9593 R_Mesh_TexMatrix(0, &layer->texmatrix);
9594 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9595 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9597 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);
9599 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);
9602 case TEXTURELAYERTYPE_TEXTURE:
9603 // singletexture unlit texture with transparency support
9604 R_Mesh_TexBind(0, layer->texture);
9605 R_Mesh_TexMatrix(0, &layer->texmatrix);
9606 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9607 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9608 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);
9610 case TEXTURELAYERTYPE_FOG:
9611 // singletexture fogging
9614 R_Mesh_TexBind(0, layer->texture);
9615 R_Mesh_TexMatrix(0, &layer->texmatrix);
9616 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9617 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9621 R_Mesh_TexBind(0, 0);
9622 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9624 // generate a color array for the fog pass
9625 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9626 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9630 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9633 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9635 GL_DepthFunc(GL_LEQUAL);
9636 GL_AlphaTest(false);
9640 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9644 r_vertexgeneric_t *batchvertex;
9647 // R_Mesh_ResetTextureState();
9648 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9650 if(rsurface.texture && rsurface.texture->currentskinframe)
9652 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9653 c[3] *= rsurface.texture->currentalpha;
9663 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9665 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9666 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9667 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9670 // brighten it up (as texture value 127 means "unlit")
9671 c[0] *= 2 * r_refdef.view.colorscale;
9672 c[1] *= 2 * r_refdef.view.colorscale;
9673 c[2] *= 2 * r_refdef.view.colorscale;
9675 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9676 c[3] *= r_wateralpha.value;
9678 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9680 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9681 GL_DepthMask(false);
9683 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9685 GL_BlendFunc(GL_ONE, GL_ONE);
9686 GL_DepthMask(false);
9688 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9690 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9691 GL_DepthMask(false);
9693 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9695 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9696 GL_DepthMask(false);
9700 GL_BlendFunc(GL_ONE, GL_ZERO);
9701 GL_DepthMask(writedepth);
9704 if (r_showsurfaces.integer == 3)
9706 rsurface.passcolor4f = NULL;
9708 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9710 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9712 rsurface.passcolor4f = NULL;
9713 rsurface.passcolor4f_vertexbuffer = 0;
9714 rsurface.passcolor4f_bufferoffset = 0;
9716 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9718 qboolean applycolor = true;
9721 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9723 r_refdef.lightmapintensity = 1;
9724 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9725 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9727 else if (FAKELIGHT_ENABLED)
9729 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9731 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9732 RSurf_DrawBatch_GL11_ApplyFakeLight();
9733 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9737 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9739 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9740 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9741 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9744 if(!rsurface.passcolor4f)
9745 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9747 RSurf_DrawBatch_GL11_ApplyAmbient();
9748 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9749 if(r_refdef.fogenabled)
9750 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9751 RSurf_DrawBatch_GL11_ClampColor();
9753 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9754 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9757 else if (!r_refdef.view.showdebug)
9759 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9760 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9761 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9763 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9764 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9766 R_Mesh_PrepareVertices_Generic_Unlock();
9769 else if (r_showsurfaces.integer == 4)
9771 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9772 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9773 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9775 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9776 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9777 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9779 R_Mesh_PrepareVertices_Generic_Unlock();
9782 else if (r_showsurfaces.integer == 2)
9785 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9786 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9787 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9789 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9790 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9791 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9792 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9793 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9794 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9795 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9797 R_Mesh_PrepareVertices_Generic_Unlock();
9798 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9802 int texturesurfaceindex;
9804 const msurface_t *surface;
9805 float surfacecolor4f[4];
9806 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9807 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9809 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9811 surface = texturesurfacelist[texturesurfaceindex];
9812 k = (int)(((size_t)surface) / sizeof(msurface_t));
9813 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9814 for (j = 0;j < surface->num_vertices;j++)
9816 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9817 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9821 R_Mesh_PrepareVertices_Generic_Unlock();
9826 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9829 RSurf_SetupDepthAndCulling();
9830 if (r_showsurfaces.integer)
9832 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9835 switch (vid.renderpath)
9837 case RENDERPATH_GL20:
9838 case RENDERPATH_D3D9:
9839 case RENDERPATH_D3D10:
9840 case RENDERPATH_D3D11:
9841 case RENDERPATH_SOFT:
9842 case RENDERPATH_GLES2:
9843 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9845 case RENDERPATH_GL13:
9846 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9848 case RENDERPATH_GL11:
9849 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9855 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9858 RSurf_SetupDepthAndCulling();
9859 if (r_showsurfaces.integer)
9861 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9864 switch (vid.renderpath)
9866 case RENDERPATH_GL20:
9867 case RENDERPATH_D3D9:
9868 case RENDERPATH_D3D10:
9869 case RENDERPATH_D3D11:
9870 case RENDERPATH_SOFT:
9871 case RENDERPATH_GLES2:
9872 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9874 case RENDERPATH_GL13:
9875 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9877 case RENDERPATH_GL11:
9878 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9884 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9887 int texturenumsurfaces, endsurface;
9889 const msurface_t *surface;
9890 #define MAXBATCH_TRANSPARENTSURFACES 256
9891 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9893 // if the model is static it doesn't matter what value we give for
9894 // wantnormals and wanttangents, so this logic uses only rules applicable
9895 // to a model, knowing that they are meaningless otherwise
9896 if (ent == r_refdef.scene.worldentity)
9897 RSurf_ActiveWorldEntity();
9898 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9899 RSurf_ActiveModelEntity(ent, false, false, false);
9902 switch (vid.renderpath)
9904 case RENDERPATH_GL20:
9905 case RENDERPATH_D3D9:
9906 case RENDERPATH_D3D10:
9907 case RENDERPATH_D3D11:
9908 case RENDERPATH_SOFT:
9909 case RENDERPATH_GLES2:
9910 RSurf_ActiveModelEntity(ent, true, true, false);
9912 case RENDERPATH_GL13:
9913 case RENDERPATH_GL11:
9914 RSurf_ActiveModelEntity(ent, true, false, false);
9919 if (r_transparentdepthmasking.integer)
9921 qboolean setup = false;
9922 for (i = 0;i < numsurfaces;i = j)
9925 surface = rsurface.modelsurfaces + surfacelist[i];
9926 texture = surface->texture;
9927 rsurface.texture = R_GetCurrentTexture(texture);
9928 rsurface.lightmaptexture = NULL;
9929 rsurface.deluxemaptexture = NULL;
9930 rsurface.uselightmaptexture = false;
9931 // scan ahead until we find a different texture
9932 endsurface = min(i + 1024, numsurfaces);
9933 texturenumsurfaces = 0;
9934 texturesurfacelist[texturenumsurfaces++] = surface;
9935 for (;j < endsurface;j++)
9937 surface = rsurface.modelsurfaces + surfacelist[j];
9938 if (texture != surface->texture)
9940 texturesurfacelist[texturenumsurfaces++] = surface;
9942 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9944 // render the range of surfaces as depth
9948 GL_ColorMask(0,0,0,0);
9951 GL_BlendFunc(GL_ONE, GL_ZERO);
9953 // R_Mesh_ResetTextureState();
9954 R_SetupShader_DepthOrShadow();
9956 RSurf_SetupDepthAndCulling();
9957 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9958 if (rsurface.batchvertex3fbuffer)
9959 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9961 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9965 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9968 for (i = 0;i < numsurfaces;i = j)
9971 surface = rsurface.modelsurfaces + surfacelist[i];
9972 texture = surface->texture;
9973 rsurface.texture = R_GetCurrentTexture(texture);
9974 // scan ahead until we find a different texture
9975 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9976 texturenumsurfaces = 0;
9977 texturesurfacelist[texturenumsurfaces++] = surface;
9978 if(FAKELIGHT_ENABLED)
9980 rsurface.lightmaptexture = NULL;
9981 rsurface.deluxemaptexture = NULL;
9982 rsurface.uselightmaptexture = false;
9983 for (;j < endsurface;j++)
9985 surface = rsurface.modelsurfaces + surfacelist[j];
9986 if (texture != surface->texture)
9988 texturesurfacelist[texturenumsurfaces++] = surface;
9993 rsurface.lightmaptexture = surface->lightmaptexture;
9994 rsurface.deluxemaptexture = surface->deluxemaptexture;
9995 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9996 for (;j < endsurface;j++)
9998 surface = rsurface.modelsurfaces + surfacelist[j];
9999 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10001 texturesurfacelist[texturenumsurfaces++] = surface;
10004 // render the range of surfaces
10005 if (ent == r_refdef.scene.worldentity)
10006 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10008 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10010 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10013 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10015 // transparent surfaces get pushed off into the transparent queue
10016 int surfacelistindex;
10017 const msurface_t *surface;
10018 vec3_t tempcenter, center;
10019 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10021 surface = texturesurfacelist[surfacelistindex];
10022 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10023 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10024 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10025 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10026 if (queueentity->transparent_offset) // transparent offset
10028 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10029 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10030 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10032 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10036 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10038 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10040 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10042 RSurf_SetupDepthAndCulling();
10043 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10044 if (rsurface.batchvertex3fbuffer)
10045 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10047 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10051 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10053 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10056 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10059 if (!rsurface.texture->currentnumlayers)
10061 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10062 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10064 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10066 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10067 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10068 else if (!rsurface.texture->currentnumlayers)
10070 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10072 // in the deferred case, transparent surfaces were queued during prepass
10073 if (!r_shadow_usingdeferredprepass)
10074 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10078 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10079 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10084 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10087 texture_t *texture;
10088 R_FrameData_SetMark();
10089 // break the surface list down into batches by texture and use of lightmapping
10090 for (i = 0;i < numsurfaces;i = j)
10093 // texture is the base texture pointer, rsurface.texture is the
10094 // current frame/skin the texture is directing us to use (for example
10095 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10096 // use skin 1 instead)
10097 texture = surfacelist[i]->texture;
10098 rsurface.texture = R_GetCurrentTexture(texture);
10099 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10101 // if this texture is not the kind we want, skip ahead to the next one
10102 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10106 if(FAKELIGHT_ENABLED || depthonly || prepass)
10108 rsurface.lightmaptexture = NULL;
10109 rsurface.deluxemaptexture = NULL;
10110 rsurface.uselightmaptexture = false;
10111 // simply scan ahead until we find a different texture or lightmap state
10112 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10117 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10118 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10119 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10120 // simply scan ahead until we find a different texture or lightmap state
10121 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10124 // render the range of surfaces
10125 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10127 R_FrameData_ReturnToMark();
10130 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10134 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10137 if (!rsurface.texture->currentnumlayers)
10139 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10140 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10142 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10144 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10145 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10146 else if (!rsurface.texture->currentnumlayers)
10148 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10150 // in the deferred case, transparent surfaces were queued during prepass
10151 if (!r_shadow_usingdeferredprepass)
10152 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10156 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10157 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10162 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10165 texture_t *texture;
10166 R_FrameData_SetMark();
10167 // break the surface list down into batches by texture and use of lightmapping
10168 for (i = 0;i < numsurfaces;i = j)
10171 // texture is the base texture pointer, rsurface.texture is the
10172 // current frame/skin the texture is directing us to use (for example
10173 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10174 // use skin 1 instead)
10175 texture = surfacelist[i]->texture;
10176 rsurface.texture = R_GetCurrentTexture(texture);
10177 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10179 // if this texture is not the kind we want, skip ahead to the next one
10180 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10184 if(FAKELIGHT_ENABLED || depthonly || prepass)
10186 rsurface.lightmaptexture = NULL;
10187 rsurface.deluxemaptexture = NULL;
10188 rsurface.uselightmaptexture = false;
10189 // simply scan ahead until we find a different texture or lightmap state
10190 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10195 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10196 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10197 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10198 // simply scan ahead until we find a different texture or lightmap state
10199 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10202 // render the range of surfaces
10203 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10205 R_FrameData_ReturnToMark();
10208 float locboxvertex3f[6*4*3] =
10210 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10211 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10212 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10213 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10214 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10215 1,0,0, 0,0,0, 0,1,0, 1,1,0
10218 unsigned short locboxelements[6*2*3] =
10223 12,13,14, 12,14,15,
10224 16,17,18, 16,18,19,
10228 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10231 cl_locnode_t *loc = (cl_locnode_t *)ent;
10233 float vertex3f[6*4*3];
10235 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10236 GL_DepthMask(false);
10237 GL_DepthRange(0, 1);
10238 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10239 GL_DepthTest(true);
10240 GL_CullFace(GL_NONE);
10241 R_EntityMatrix(&identitymatrix);
10243 // R_Mesh_ResetTextureState();
10245 i = surfacelist[0];
10246 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10247 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10248 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10249 surfacelist[0] < 0 ? 0.5f : 0.125f);
10251 if (VectorCompare(loc->mins, loc->maxs))
10253 VectorSet(size, 2, 2, 2);
10254 VectorMA(loc->mins, -0.5f, size, mins);
10258 VectorCopy(loc->mins, mins);
10259 VectorSubtract(loc->maxs, loc->mins, size);
10262 for (i = 0;i < 6*4*3;)
10263 for (j = 0;j < 3;j++, i++)
10264 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10266 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10267 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10268 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10271 void R_DrawLocs(void)
10274 cl_locnode_t *loc, *nearestloc;
10276 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10277 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10279 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10280 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10284 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10286 if (decalsystem->decals)
10287 Mem_Free(decalsystem->decals);
10288 memset(decalsystem, 0, sizeof(*decalsystem));
10291 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)
10294 tridecal_t *decals;
10297 // expand or initialize the system
10298 if (decalsystem->maxdecals <= decalsystem->numdecals)
10300 decalsystem_t old = *decalsystem;
10301 qboolean useshortelements;
10302 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10303 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10304 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)));
10305 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10306 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10307 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10308 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10309 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10310 if (decalsystem->numdecals)
10311 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10313 Mem_Free(old.decals);
10314 for (i = 0;i < decalsystem->maxdecals*3;i++)
10315 decalsystem->element3i[i] = i;
10316 if (useshortelements)
10317 for (i = 0;i < decalsystem->maxdecals*3;i++)
10318 decalsystem->element3s[i] = i;
10321 // grab a decal and search for another free slot for the next one
10322 decals = decalsystem->decals;
10323 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10324 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10326 decalsystem->freedecal = i;
10327 if (decalsystem->numdecals <= i)
10328 decalsystem->numdecals = i + 1;
10330 // initialize the decal
10332 decal->triangleindex = triangleindex;
10333 decal->surfaceindex = surfaceindex;
10334 decal->decalsequence = decalsequence;
10335 decal->color4f[0][0] = c0[0];
10336 decal->color4f[0][1] = c0[1];
10337 decal->color4f[0][2] = c0[2];
10338 decal->color4f[0][3] = 1;
10339 decal->color4f[1][0] = c1[0];
10340 decal->color4f[1][1] = c1[1];
10341 decal->color4f[1][2] = c1[2];
10342 decal->color4f[1][3] = 1;
10343 decal->color4f[2][0] = c2[0];
10344 decal->color4f[2][1] = c2[1];
10345 decal->color4f[2][2] = c2[2];
10346 decal->color4f[2][3] = 1;
10347 decal->vertex3f[0][0] = v0[0];
10348 decal->vertex3f[0][1] = v0[1];
10349 decal->vertex3f[0][2] = v0[2];
10350 decal->vertex3f[1][0] = v1[0];
10351 decal->vertex3f[1][1] = v1[1];
10352 decal->vertex3f[1][2] = v1[2];
10353 decal->vertex3f[2][0] = v2[0];
10354 decal->vertex3f[2][1] = v2[1];
10355 decal->vertex3f[2][2] = v2[2];
10356 decal->texcoord2f[0][0] = t0[0];
10357 decal->texcoord2f[0][1] = t0[1];
10358 decal->texcoord2f[1][0] = t1[0];
10359 decal->texcoord2f[1][1] = t1[1];
10360 decal->texcoord2f[2][0] = t2[0];
10361 decal->texcoord2f[2][1] = t2[1];
10364 extern cvar_t cl_decals_bias;
10365 extern cvar_t cl_decals_models;
10366 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10367 // baseparms, parms, temps
10368 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)
10373 const float *vertex3f;
10374 const float *normal3f;
10376 float points[2][9][3];
10383 e = rsurface.modelelement3i + 3*triangleindex;
10385 vertex3f = rsurface.modelvertex3f;
10386 normal3f = rsurface.modelnormal3f;
10390 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10392 index = 3*e[cornerindex];
10393 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10398 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10400 index = 3*e[cornerindex];
10401 VectorCopy(vertex3f + index, v[cornerindex]);
10406 //TriangleNormal(v[0], v[1], v[2], normal);
10407 //if (DotProduct(normal, localnormal) < 0.0f)
10409 // clip by each of the box planes formed from the projection matrix
10410 // if anything survives, we emit the decal
10411 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]);
10414 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]);
10417 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]);
10420 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]);
10423 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]);
10426 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]);
10429 // some part of the triangle survived, so we have to accept it...
10432 // dynamic always uses the original triangle
10434 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10436 index = 3*e[cornerindex];
10437 VectorCopy(vertex3f + index, v[cornerindex]);
10440 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10442 // convert vertex positions to texcoords
10443 Matrix4x4_Transform(projection, v[cornerindex], temp);
10444 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10445 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10446 // calculate distance fade from the projection origin
10447 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10448 f = bound(0.0f, f, 1.0f);
10449 c[cornerindex][0] = r * f;
10450 c[cornerindex][1] = g * f;
10451 c[cornerindex][2] = b * f;
10452 c[cornerindex][3] = 1.0f;
10453 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10456 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);
10458 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10459 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);
10461 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)
10463 matrix4x4_t projection;
10464 decalsystem_t *decalsystem;
10467 const msurface_t *surface;
10468 const msurface_t *surfaces;
10469 const int *surfacelist;
10470 const texture_t *texture;
10472 int numsurfacelist;
10473 int surfacelistindex;
10476 float localorigin[3];
10477 float localnormal[3];
10478 float localmins[3];
10479 float localmaxs[3];
10482 float planes[6][4];
10485 int bih_triangles_count;
10486 int bih_triangles[256];
10487 int bih_surfaces[256];
10489 decalsystem = &ent->decalsystem;
10490 model = ent->model;
10491 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10493 R_DecalSystem_Reset(&ent->decalsystem);
10497 if (!model->brush.data_leafs && !cl_decals_models.integer)
10499 if (decalsystem->model)
10500 R_DecalSystem_Reset(decalsystem);
10504 if (decalsystem->model != model)
10505 R_DecalSystem_Reset(decalsystem);
10506 decalsystem->model = model;
10508 RSurf_ActiveModelEntity(ent, true, false, false);
10510 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10511 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10512 VectorNormalize(localnormal);
10513 localsize = worldsize*rsurface.inversematrixscale;
10514 localmins[0] = localorigin[0] - localsize;
10515 localmins[1] = localorigin[1] - localsize;
10516 localmins[2] = localorigin[2] - localsize;
10517 localmaxs[0] = localorigin[0] + localsize;
10518 localmaxs[1] = localorigin[1] + localsize;
10519 localmaxs[2] = localorigin[2] + localsize;
10521 //VectorCopy(localnormal, planes[4]);
10522 //VectorVectors(planes[4], planes[2], planes[0]);
10523 AnglesFromVectors(angles, localnormal, NULL, false);
10524 AngleVectors(angles, planes[0], planes[2], planes[4]);
10525 VectorNegate(planes[0], planes[1]);
10526 VectorNegate(planes[2], planes[3]);
10527 VectorNegate(planes[4], planes[5]);
10528 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10529 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10530 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10531 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10532 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10533 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10538 matrix4x4_t forwardprojection;
10539 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10540 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10545 float projectionvector[4][3];
10546 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10547 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10548 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10549 projectionvector[0][0] = planes[0][0] * ilocalsize;
10550 projectionvector[0][1] = planes[1][0] * ilocalsize;
10551 projectionvector[0][2] = planes[2][0] * ilocalsize;
10552 projectionvector[1][0] = planes[0][1] * ilocalsize;
10553 projectionvector[1][1] = planes[1][1] * ilocalsize;
10554 projectionvector[1][2] = planes[2][1] * ilocalsize;
10555 projectionvector[2][0] = planes[0][2] * ilocalsize;
10556 projectionvector[2][1] = planes[1][2] * ilocalsize;
10557 projectionvector[2][2] = planes[2][2] * ilocalsize;
10558 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10559 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10560 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10561 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10565 dynamic = model->surfmesh.isanimated;
10566 numsurfacelist = model->nummodelsurfaces;
10567 surfacelist = model->sortedmodelsurfaces;
10568 surfaces = model->data_surfaces;
10571 bih_triangles_count = -1;
10574 if(model->render_bih.numleafs)
10575 bih = &model->render_bih;
10576 else if(model->collision_bih.numleafs)
10577 bih = &model->collision_bih;
10580 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10581 if(bih_triangles_count == 0)
10583 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10585 if(bih_triangles_count > 0)
10587 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10589 surfaceindex = bih_surfaces[triangleindex];
10590 surface = surfaces + surfaceindex;
10591 texture = surface->texture;
10592 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10594 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10596 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10601 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10603 surfaceindex = surfacelist[surfacelistindex];
10604 surface = surfaces + surfaceindex;
10605 // check cull box first because it rejects more than any other check
10606 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10608 // skip transparent surfaces
10609 texture = surface->texture;
10610 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10612 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10614 numtriangles = surface->num_triangles;
10615 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10616 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10621 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10622 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)
10624 int renderentityindex;
10625 float worldmins[3];
10626 float worldmaxs[3];
10627 entity_render_t *ent;
10629 if (!cl_decals_newsystem.integer)
10632 worldmins[0] = worldorigin[0] - worldsize;
10633 worldmins[1] = worldorigin[1] - worldsize;
10634 worldmins[2] = worldorigin[2] - worldsize;
10635 worldmaxs[0] = worldorigin[0] + worldsize;
10636 worldmaxs[1] = worldorigin[1] + worldsize;
10637 worldmaxs[2] = worldorigin[2] + worldsize;
10639 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10641 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10643 ent = r_refdef.scene.entities[renderentityindex];
10644 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10647 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10651 typedef struct r_decalsystem_splatqueue_s
10653 vec3_t worldorigin;
10654 vec3_t worldnormal;
10660 r_decalsystem_splatqueue_t;
10662 int r_decalsystem_numqueued = 0;
10663 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10665 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)
10667 r_decalsystem_splatqueue_t *queue;
10669 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10672 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10673 VectorCopy(worldorigin, queue->worldorigin);
10674 VectorCopy(worldnormal, queue->worldnormal);
10675 Vector4Set(queue->color, r, g, b, a);
10676 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10677 queue->worldsize = worldsize;
10678 queue->decalsequence = cl.decalsequence++;
10681 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10684 r_decalsystem_splatqueue_t *queue;
10686 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10687 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);
10688 r_decalsystem_numqueued = 0;
10691 extern cvar_t cl_decals_max;
10692 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10695 decalsystem_t *decalsystem = &ent->decalsystem;
10702 if (!decalsystem->numdecals)
10705 if (r_showsurfaces.integer)
10708 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10710 R_DecalSystem_Reset(decalsystem);
10714 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10715 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10717 if (decalsystem->lastupdatetime)
10718 frametime = (cl.time - decalsystem->lastupdatetime);
10721 decalsystem->lastupdatetime = cl.time;
10722 decal = decalsystem->decals;
10723 numdecals = decalsystem->numdecals;
10725 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10727 if (decal->color4f[0][3])
10729 decal->lived += frametime;
10730 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10732 memset(decal, 0, sizeof(*decal));
10733 if (decalsystem->freedecal > i)
10734 decalsystem->freedecal = i;
10738 decal = decalsystem->decals;
10739 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10742 // collapse the array by shuffling the tail decals into the gaps
10745 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10746 decalsystem->freedecal++;
10747 if (decalsystem->freedecal == numdecals)
10749 decal[decalsystem->freedecal] = decal[--numdecals];
10752 decalsystem->numdecals = numdecals;
10754 if (numdecals <= 0)
10756 // if there are no decals left, reset decalsystem
10757 R_DecalSystem_Reset(decalsystem);
10761 extern skinframe_t *decalskinframe;
10762 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10765 decalsystem_t *decalsystem = &ent->decalsystem;
10774 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10777 numdecals = decalsystem->numdecals;
10781 if (r_showsurfaces.integer)
10784 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10786 R_DecalSystem_Reset(decalsystem);
10790 // if the model is static it doesn't matter what value we give for
10791 // wantnormals and wanttangents, so this logic uses only rules applicable
10792 // to a model, knowing that they are meaningless otherwise
10793 if (ent == r_refdef.scene.worldentity)
10794 RSurf_ActiveWorldEntity();
10796 RSurf_ActiveModelEntity(ent, false, false, false);
10798 decalsystem->lastupdatetime = cl.time;
10799 decal = decalsystem->decals;
10801 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10803 // update vertex positions for animated models
10804 v3f = decalsystem->vertex3f;
10805 c4f = decalsystem->color4f;
10806 t2f = decalsystem->texcoord2f;
10807 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10809 if (!decal->color4f[0][3])
10812 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10815 // update color values for fading decals
10816 if (decal->lived >= cl_decals_time.value)
10817 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10821 c4f[ 0] = decal->color4f[0][0] * alpha;
10822 c4f[ 1] = decal->color4f[0][1] * alpha;
10823 c4f[ 2] = decal->color4f[0][2] * alpha;
10825 c4f[ 4] = decal->color4f[1][0] * alpha;
10826 c4f[ 5] = decal->color4f[1][1] * alpha;
10827 c4f[ 6] = decal->color4f[1][2] * alpha;
10829 c4f[ 8] = decal->color4f[2][0] * alpha;
10830 c4f[ 9] = decal->color4f[2][1] * alpha;
10831 c4f[10] = decal->color4f[2][2] * alpha;
10834 t2f[0] = decal->texcoord2f[0][0];
10835 t2f[1] = decal->texcoord2f[0][1];
10836 t2f[2] = decal->texcoord2f[1][0];
10837 t2f[3] = decal->texcoord2f[1][1];
10838 t2f[4] = decal->texcoord2f[2][0];
10839 t2f[5] = decal->texcoord2f[2][1];
10841 // update vertex positions for animated models
10842 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10844 e = rsurface.modelelement3i + 3*decal->triangleindex;
10845 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10846 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10847 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10851 VectorCopy(decal->vertex3f[0], v3f);
10852 VectorCopy(decal->vertex3f[1], v3f + 3);
10853 VectorCopy(decal->vertex3f[2], v3f + 6);
10856 if (r_refdef.fogenabled)
10858 alpha = RSurf_FogVertex(v3f);
10859 VectorScale(c4f, alpha, c4f);
10860 alpha = RSurf_FogVertex(v3f + 3);
10861 VectorScale(c4f + 4, alpha, c4f + 4);
10862 alpha = RSurf_FogVertex(v3f + 6);
10863 VectorScale(c4f + 8, alpha, c4f + 8);
10874 r_refdef.stats.drawndecals += numtris;
10876 // now render the decals all at once
10877 // (this assumes they all use one particle font texture!)
10878 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);
10879 // R_Mesh_ResetTextureState();
10880 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10881 GL_DepthMask(false);
10882 GL_DepthRange(0, 1);
10883 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10884 GL_DepthTest(true);
10885 GL_CullFace(GL_NONE);
10886 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10887 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10888 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10892 static void R_DrawModelDecals(void)
10896 // fade faster when there are too many decals
10897 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10898 for (i = 0;i < r_refdef.scene.numentities;i++)
10899 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10901 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10902 for (i = 0;i < r_refdef.scene.numentities;i++)
10903 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10904 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10906 R_DecalSystem_ApplySplatEntitiesQueue();
10908 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10909 for (i = 0;i < r_refdef.scene.numentities;i++)
10910 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10912 r_refdef.stats.totaldecals += numdecals;
10914 if (r_showsurfaces.integer)
10917 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10919 for (i = 0;i < r_refdef.scene.numentities;i++)
10921 if (!r_refdef.viewcache.entityvisible[i])
10923 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10924 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10928 extern cvar_t mod_collision_bih;
10929 void R_DrawDebugModel(void)
10931 entity_render_t *ent = rsurface.entity;
10932 int i, j, k, l, flagsmask;
10933 const msurface_t *surface;
10934 dp_model_t *model = ent->model;
10937 switch(vid.renderpath)
10939 case RENDERPATH_GL11:
10940 case RENDERPATH_GL13:
10941 case RENDERPATH_GL20:
10943 case RENDERPATH_D3D9:
10944 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10946 case RENDERPATH_D3D10:
10947 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10949 case RENDERPATH_D3D11:
10950 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10952 case RENDERPATH_SOFT:
10953 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10955 case RENDERPATH_GLES2:
10956 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10960 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10962 // R_Mesh_ResetTextureState();
10963 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10964 GL_DepthRange(0, 1);
10965 GL_DepthTest(!r_showdisabledepthtest.integer);
10966 GL_DepthMask(false);
10967 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10969 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10973 qboolean cullbox = ent == r_refdef.scene.worldentity;
10974 const q3mbrush_t *brush;
10975 const bih_t *bih = &model->collision_bih;
10976 const bih_leaf_t *bihleaf;
10977 float vertex3f[3][3];
10978 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10980 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10982 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10984 switch (bihleaf->type)
10987 brush = model->brush.data_brushes + bihleaf->itemindex;
10988 if (brush->colbrushf && brush->colbrushf->numtriangles)
10990 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);
10991 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10992 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10995 case BIH_COLLISIONTRIANGLE:
10996 triangleindex = bihleaf->itemindex;
10997 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10998 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10999 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11000 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);
11001 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11002 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11004 case BIH_RENDERTRIANGLE:
11005 triangleindex = bihleaf->itemindex;
11006 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11007 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11008 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11009 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);
11010 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11011 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11017 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11019 if (r_showtris.integer || (r_shownormals.value != 0))
11021 if (r_showdisabledepthtest.integer)
11023 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11024 GL_DepthMask(false);
11028 GL_BlendFunc(GL_ONE, GL_ZERO);
11029 GL_DepthMask(true);
11031 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11033 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11035 rsurface.texture = R_GetCurrentTexture(surface->texture);
11036 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11038 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11039 if (r_showtris.value > 0)
11041 if (!rsurface.texture->currentlayers->depthmask)
11042 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11043 else if (ent == r_refdef.scene.worldentity)
11044 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11046 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11047 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11048 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11050 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11053 if (r_shownormals.value < 0)
11055 qglBegin(GL_LINES);
11056 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11058 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11059 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11060 qglVertex3f(v[0], v[1], v[2]);
11061 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11062 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11063 qglVertex3f(v[0], v[1], v[2]);
11068 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11070 qglBegin(GL_LINES);
11071 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11073 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11074 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11075 qglVertex3f(v[0], v[1], v[2]);
11076 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11077 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11078 qglVertex3f(v[0], v[1], v[2]);
11082 qglBegin(GL_LINES);
11083 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11085 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11086 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11087 qglVertex3f(v[0], v[1], v[2]);
11088 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11089 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11090 qglVertex3f(v[0], v[1], v[2]);
11094 qglBegin(GL_LINES);
11095 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11097 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11098 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11099 qglVertex3f(v[0], v[1], v[2]);
11100 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11101 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11102 qglVertex3f(v[0], v[1], v[2]);
11109 rsurface.texture = NULL;
11113 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11114 int r_maxsurfacelist = 0;
11115 const msurface_t **r_surfacelist = NULL;
11116 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11118 int i, j, endj, flagsmask;
11119 dp_model_t *model = r_refdef.scene.worldmodel;
11120 msurface_t *surfaces;
11121 unsigned char *update;
11122 int numsurfacelist = 0;
11126 if (r_maxsurfacelist < model->num_surfaces)
11128 r_maxsurfacelist = model->num_surfaces;
11130 Mem_Free((msurface_t**)r_surfacelist);
11131 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11134 RSurf_ActiveWorldEntity();
11136 surfaces = model->data_surfaces;
11137 update = model->brushq1.lightmapupdateflags;
11139 // update light styles on this submodel
11140 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11142 model_brush_lightstyleinfo_t *style;
11143 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11145 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11147 int *list = style->surfacelist;
11148 style->value = r_refdef.scene.lightstylevalue[style->style];
11149 for (j = 0;j < style->numsurfaces;j++)
11150 update[list[j]] = true;
11155 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11159 R_DrawDebugModel();
11160 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11164 rsurface.lightmaptexture = NULL;
11165 rsurface.deluxemaptexture = NULL;
11166 rsurface.uselightmaptexture = false;
11167 rsurface.texture = NULL;
11168 rsurface.rtlight = NULL;
11169 numsurfacelist = 0;
11170 // add visible surfaces to draw list
11171 for (i = 0;i < model->nummodelsurfaces;i++)
11173 j = model->sortedmodelsurfaces[i];
11174 if (r_refdef.viewcache.world_surfacevisible[j])
11175 r_surfacelist[numsurfacelist++] = surfaces + j;
11177 // update lightmaps if needed
11178 if (model->brushq1.firstrender)
11180 model->brushq1.firstrender = false;
11181 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11183 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11187 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11188 if (r_refdef.viewcache.world_surfacevisible[j])
11190 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11192 // don't do anything if there were no surfaces
11193 if (!numsurfacelist)
11195 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11198 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11200 // add to stats if desired
11201 if (r_speeds.integer && !skysurfaces && !depthonly)
11203 r_refdef.stats.world_surfaces += numsurfacelist;
11204 for (j = 0;j < numsurfacelist;j++)
11205 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11208 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11211 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11213 int i, j, endj, flagsmask;
11214 dp_model_t *model = ent->model;
11215 msurface_t *surfaces;
11216 unsigned char *update;
11217 int numsurfacelist = 0;
11221 if (r_maxsurfacelist < model->num_surfaces)
11223 r_maxsurfacelist = model->num_surfaces;
11225 Mem_Free((msurface_t **)r_surfacelist);
11226 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11229 // if the model is static it doesn't matter what value we give for
11230 // wantnormals and wanttangents, so this logic uses only rules applicable
11231 // to a model, knowing that they are meaningless otherwise
11232 if (ent == r_refdef.scene.worldentity)
11233 RSurf_ActiveWorldEntity();
11234 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11235 RSurf_ActiveModelEntity(ent, false, false, false);
11237 RSurf_ActiveModelEntity(ent, true, true, true);
11238 else if (depthonly)
11240 switch (vid.renderpath)
11242 case RENDERPATH_GL20:
11243 case RENDERPATH_D3D9:
11244 case RENDERPATH_D3D10:
11245 case RENDERPATH_D3D11:
11246 case RENDERPATH_SOFT:
11247 case RENDERPATH_GLES2:
11248 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11250 case RENDERPATH_GL13:
11251 case RENDERPATH_GL11:
11252 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11258 switch (vid.renderpath)
11260 case RENDERPATH_GL20:
11261 case RENDERPATH_D3D9:
11262 case RENDERPATH_D3D10:
11263 case RENDERPATH_D3D11:
11264 case RENDERPATH_SOFT:
11265 case RENDERPATH_GLES2:
11266 RSurf_ActiveModelEntity(ent, true, true, false);
11268 case RENDERPATH_GL13:
11269 case RENDERPATH_GL11:
11270 RSurf_ActiveModelEntity(ent, true, false, false);
11275 surfaces = model->data_surfaces;
11276 update = model->brushq1.lightmapupdateflags;
11278 // update light styles
11279 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11281 model_brush_lightstyleinfo_t *style;
11282 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11284 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11286 int *list = style->surfacelist;
11287 style->value = r_refdef.scene.lightstylevalue[style->style];
11288 for (j = 0;j < style->numsurfaces;j++)
11289 update[list[j]] = true;
11294 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11298 R_DrawDebugModel();
11299 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11303 rsurface.lightmaptexture = NULL;
11304 rsurface.deluxemaptexture = NULL;
11305 rsurface.uselightmaptexture = false;
11306 rsurface.texture = NULL;
11307 rsurface.rtlight = NULL;
11308 numsurfacelist = 0;
11309 // add visible surfaces to draw list
11310 for (i = 0;i < model->nummodelsurfaces;i++)
11311 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11312 // don't do anything if there were no surfaces
11313 if (!numsurfacelist)
11315 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11318 // update lightmaps if needed
11322 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11327 R_BuildLightMap(ent, surfaces + j);
11332 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11334 R_BuildLightMap(ent, surfaces + j);
11335 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11337 // add to stats if desired
11338 if (r_speeds.integer && !skysurfaces && !depthonly)
11340 r_refdef.stats.entities_surfaces += numsurfacelist;
11341 for (j = 0;j < numsurfacelist;j++)
11342 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11345 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11348 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11350 static texture_t texture;
11351 static msurface_t surface;
11352 const msurface_t *surfacelist = &surface;
11354 // fake enough texture and surface state to render this geometry
11356 texture.update_lastrenderframe = -1; // regenerate this texture
11357 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11358 texture.currentskinframe = skinframe;
11359 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11360 texture.offsetmapping = OFFSETMAPPING_OFF;
11361 texture.offsetscale = 1;
11362 texture.specularscalemod = 1;
11363 texture.specularpowermod = 1;
11365 surface.texture = &texture;
11366 surface.num_triangles = numtriangles;
11367 surface.num_firsttriangle = firsttriangle;
11368 surface.num_vertices = numvertices;
11369 surface.num_firstvertex = firstvertex;
11372 rsurface.texture = R_GetCurrentTexture(surface.texture);
11373 rsurface.lightmaptexture = NULL;
11374 rsurface.deluxemaptexture = NULL;
11375 rsurface.uselightmaptexture = false;
11376 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11379 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)
11381 static msurface_t surface;
11382 const msurface_t *surfacelist = &surface;
11384 // fake enough texture and surface state to render this geometry
11385 surface.texture = texture;
11386 surface.num_triangles = numtriangles;
11387 surface.num_firsttriangle = firsttriangle;
11388 surface.num_vertices = numvertices;
11389 surface.num_firstvertex = firstvertex;
11392 rsurface.texture = R_GetCurrentTexture(surface.texture);
11393 rsurface.lightmaptexture = NULL;
11394 rsurface.deluxemaptexture = NULL;
11395 rsurface.uselightmaptexture = false;
11396 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);