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 case RENDERPATH_GLES2:
3838 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3839 Cvar_SetValueQuick(&gl_combine, 1);
3840 Cvar_SetValueQuick(&r_glsl, 1);
3841 r_loadnormalmap = true;
3845 case RENDERPATH_GL13:
3846 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3847 Cvar_SetValueQuick(&gl_combine, 1);
3848 Cvar_SetValueQuick(&r_glsl, 0);
3849 r_loadnormalmap = false;
3850 r_loadgloss = false;
3853 case RENDERPATH_GL11:
3854 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3855 Cvar_SetValueQuick(&gl_combine, 0);
3856 Cvar_SetValueQuick(&r_glsl, 0);
3857 r_loadnormalmap = false;
3858 r_loadgloss = false;
3864 R_FrameData_Reset();
3868 memset(r_queries, 0, sizeof(r_queries));
3870 r_qwskincache = NULL;
3871 r_qwskincache_size = 0;
3873 // due to caching of texture_t references, the collision cache must be reset
3874 Collision_Cache_Reset(true);
3876 // set up r_skinframe loading system for textures
3877 memset(&r_skinframe, 0, sizeof(r_skinframe));
3878 r_skinframe.loadsequence = 1;
3879 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3881 r_main_texturepool = R_AllocTexturePool();
3882 R_BuildBlankTextures();
3884 if (vid.support.arb_texture_cube_map)
3887 R_BuildNormalizationCube();
3889 r_texture_fogattenuation = NULL;
3890 r_texture_fogheighttexture = NULL;
3891 r_texture_gammaramps = NULL;
3892 //r_texture_fogintensity = NULL;
3893 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3894 memset(&r_waterstate, 0, sizeof(r_waterstate));
3895 r_glsl_permutation = NULL;
3896 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3897 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3898 glslshaderstring = NULL;
3900 r_hlsl_permutation = NULL;
3901 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3902 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3904 hlslshaderstring = NULL;
3905 memset(&r_svbsp, 0, sizeof (r_svbsp));
3907 r_refdef.fogmasktable_density = 0;
3910 void gl_main_shutdown(void)
3913 R_FrameData_Reset();
3915 R_Main_FreeViewCache();
3917 switch(vid.renderpath)
3919 case RENDERPATH_GL11:
3920 case RENDERPATH_GL13:
3921 case RENDERPATH_GL20:
3922 case RENDERPATH_GLES2:
3924 qglDeleteQueriesARB(r_maxqueries, r_queries);
3926 case RENDERPATH_D3D9:
3927 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3929 case RENDERPATH_D3D10:
3930 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3932 case RENDERPATH_D3D11:
3933 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3935 case RENDERPATH_SOFT:
3941 memset(r_queries, 0, sizeof(r_queries));
3943 r_qwskincache = NULL;
3944 r_qwskincache_size = 0;
3946 // clear out the r_skinframe state
3947 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3948 memset(&r_skinframe, 0, sizeof(r_skinframe));
3951 Mem_Free(r_svbsp.nodes);
3952 memset(&r_svbsp, 0, sizeof (r_svbsp));
3953 R_FreeTexturePool(&r_main_texturepool);
3954 loadingscreentexture = NULL;
3955 r_texture_blanknormalmap = NULL;
3956 r_texture_white = NULL;
3957 r_texture_grey128 = NULL;
3958 r_texture_black = NULL;
3959 r_texture_whitecube = NULL;
3960 r_texture_normalizationcube = NULL;
3961 r_texture_fogattenuation = NULL;
3962 r_texture_fogheighttexture = NULL;
3963 r_texture_gammaramps = NULL;
3964 r_texture_numcubemaps = 0;
3965 //r_texture_fogintensity = NULL;
3966 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3967 memset(&r_waterstate, 0, sizeof(r_waterstate));
3970 r_glsl_permutation = NULL;
3971 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3972 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3973 glslshaderstring = NULL;
3975 r_hlsl_permutation = NULL;
3976 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3977 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3979 hlslshaderstring = NULL;
3982 extern void CL_ParseEntityLump(char *entitystring);
3983 void gl_main_newmap(void)
3985 // FIXME: move this code to client
3986 char *entities, entname[MAX_QPATH];
3988 Mem_Free(r_qwskincache);
3989 r_qwskincache = NULL;
3990 r_qwskincache_size = 0;
3993 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3994 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3996 CL_ParseEntityLump(entities);
4000 if (cl.worldmodel->brush.entities)
4001 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4003 R_Main_FreeViewCache();
4005 R_FrameData_Reset();
4008 void GL_Main_Init(void)
4010 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4012 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4013 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4014 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4015 if (gamemode == GAME_NEHAHRA)
4017 Cvar_RegisterVariable (&gl_fogenable);
4018 Cvar_RegisterVariable (&gl_fogdensity);
4019 Cvar_RegisterVariable (&gl_fogred);
4020 Cvar_RegisterVariable (&gl_foggreen);
4021 Cvar_RegisterVariable (&gl_fogblue);
4022 Cvar_RegisterVariable (&gl_fogstart);
4023 Cvar_RegisterVariable (&gl_fogend);
4024 Cvar_RegisterVariable (&gl_skyclip);
4026 Cvar_RegisterVariable(&r_motionblur);
4027 Cvar_RegisterVariable(&r_motionblur_maxblur);
4028 Cvar_RegisterVariable(&r_motionblur_bmin);
4029 Cvar_RegisterVariable(&r_motionblur_vmin);
4030 Cvar_RegisterVariable(&r_motionblur_vmax);
4031 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4032 Cvar_RegisterVariable(&r_motionblur_randomize);
4033 Cvar_RegisterVariable(&r_damageblur);
4034 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4035 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4036 Cvar_RegisterVariable(&r_equalize_entities_by);
4037 Cvar_RegisterVariable(&r_equalize_entities_to);
4038 Cvar_RegisterVariable(&r_depthfirst);
4039 Cvar_RegisterVariable(&r_useinfinitefarclip);
4040 Cvar_RegisterVariable(&r_farclip_base);
4041 Cvar_RegisterVariable(&r_farclip_world);
4042 Cvar_RegisterVariable(&r_nearclip);
4043 Cvar_RegisterVariable(&r_showbboxes);
4044 Cvar_RegisterVariable(&r_showsurfaces);
4045 Cvar_RegisterVariable(&r_showtris);
4046 Cvar_RegisterVariable(&r_shownormals);
4047 Cvar_RegisterVariable(&r_showlighting);
4048 Cvar_RegisterVariable(&r_showshadowvolumes);
4049 Cvar_RegisterVariable(&r_showcollisionbrushes);
4050 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4051 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4052 Cvar_RegisterVariable(&r_showdisabledepthtest);
4053 Cvar_RegisterVariable(&r_drawportals);
4054 Cvar_RegisterVariable(&r_drawentities);
4055 Cvar_RegisterVariable(&r_draw2d);
4056 Cvar_RegisterVariable(&r_drawworld);
4057 Cvar_RegisterVariable(&r_cullentities_trace);
4058 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4059 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4060 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4061 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4062 Cvar_RegisterVariable(&r_drawviewmodel);
4063 Cvar_RegisterVariable(&r_drawexteriormodel);
4064 Cvar_RegisterVariable(&r_speeds);
4065 Cvar_RegisterVariable(&r_fullbrights);
4066 Cvar_RegisterVariable(&r_wateralpha);
4067 Cvar_RegisterVariable(&r_dynamic);
4068 Cvar_RegisterVariable(&r_fakelight);
4069 Cvar_RegisterVariable(&r_fakelight_intensity);
4070 Cvar_RegisterVariable(&r_fullbright);
4071 Cvar_RegisterVariable(&r_shadows);
4072 Cvar_RegisterVariable(&r_shadows_darken);
4073 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4074 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4075 Cvar_RegisterVariable(&r_shadows_throwdistance);
4076 Cvar_RegisterVariable(&r_shadows_throwdirection);
4077 Cvar_RegisterVariable(&r_shadows_focus);
4078 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4079 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4080 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4081 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4082 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4083 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4084 Cvar_RegisterVariable(&r_fog_exp2);
4085 Cvar_RegisterVariable(&r_fog_clear);
4086 Cvar_RegisterVariable(&r_drawfog);
4087 Cvar_RegisterVariable(&r_transparentdepthmasking);
4088 Cvar_RegisterVariable(&r_texture_dds_load);
4089 Cvar_RegisterVariable(&r_texture_dds_save);
4090 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4091 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4092 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4093 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4094 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4095 Cvar_RegisterVariable(&r_textureunits);
4096 Cvar_RegisterVariable(&gl_combine);
4097 Cvar_RegisterVariable(&r_viewfbo);
4098 Cvar_RegisterVariable(&r_viewscale);
4099 Cvar_RegisterVariable(&r_glsl);
4100 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4101 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4102 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4103 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4104 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4105 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4106 Cvar_RegisterVariable(&r_glsl_postprocess);
4107 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4108 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4109 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4110 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4111 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4112 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4113 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4114 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4116 Cvar_RegisterVariable(&r_water);
4117 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4118 Cvar_RegisterVariable(&r_water_clippingplanebias);
4119 Cvar_RegisterVariable(&r_water_refractdistort);
4120 Cvar_RegisterVariable(&r_water_reflectdistort);
4121 Cvar_RegisterVariable(&r_water_scissormode);
4122 Cvar_RegisterVariable(&r_lerpsprites);
4123 Cvar_RegisterVariable(&r_lerpmodels);
4124 Cvar_RegisterVariable(&r_lerplightstyles);
4125 Cvar_RegisterVariable(&r_waterscroll);
4126 Cvar_RegisterVariable(&r_bloom);
4127 Cvar_RegisterVariable(&r_bloom_colorscale);
4128 Cvar_RegisterVariable(&r_bloom_brighten);
4129 Cvar_RegisterVariable(&r_bloom_blur);
4130 Cvar_RegisterVariable(&r_bloom_resolution);
4131 Cvar_RegisterVariable(&r_bloom_colorexponent);
4132 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4133 Cvar_RegisterVariable(&r_hdr);
4134 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4135 Cvar_RegisterVariable(&r_hdr_glowintensity);
4136 Cvar_RegisterVariable(&r_hdr_range);
4137 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4138 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4139 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4140 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4141 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4142 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4143 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4144 Cvar_RegisterVariable(&developer_texturelogging);
4145 Cvar_RegisterVariable(&gl_lightmaps);
4146 Cvar_RegisterVariable(&r_test);
4147 Cvar_RegisterVariable(&r_glsl_saturation);
4148 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4149 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4150 Cvar_RegisterVariable(&r_framedatasize);
4151 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4152 Cvar_SetValue("r_fullbrights", 0);
4153 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4155 Cvar_RegisterVariable(&r_track_sprites);
4156 Cvar_RegisterVariable(&r_track_sprites_flags);
4157 Cvar_RegisterVariable(&r_track_sprites_scalew);
4158 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4159 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4160 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4161 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4162 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4165 extern void R_Textures_Init(void);
4166 extern void GL_Draw_Init(void);
4167 extern void GL_Main_Init(void);
4168 extern void R_Shadow_Init(void);
4169 extern void R_Sky_Init(void);
4170 extern void GL_Surf_Init(void);
4171 extern void R_Particles_Init(void);
4172 extern void R_Explosion_Init(void);
4173 extern void gl_backend_init(void);
4174 extern void Sbar_Init(void);
4175 extern void R_LightningBeams_Init(void);
4176 extern void Mod_RenderInit(void);
4177 extern void Font_Init(void);
4179 void Render_Init(void)
4192 R_LightningBeams_Init();
4201 extern char *ENGINE_EXTENSIONS;
4204 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4205 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4206 gl_version = (const char *)qglGetString(GL_VERSION);
4207 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4211 if (!gl_platformextensions)
4212 gl_platformextensions = "";
4214 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4215 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4216 Con_Printf("GL_VERSION: %s\n", gl_version);
4217 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4218 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4220 VID_CheckExtensions();
4222 // LordHavoc: report supported extensions
4223 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4225 // clear to black (loading plaque will be seen over this)
4226 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4229 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4233 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4235 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4238 p = r_refdef.view.frustum + i;
4243 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4247 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4251 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4255 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4259 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4263 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4267 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4271 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4279 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4283 for (i = 0;i < numplanes;i++)
4290 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4294 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4298 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4302 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4306 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4310 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4314 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4318 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4326 //==================================================================================
4328 // LordHavoc: this stores temporary data used within the same frame
4330 typedef struct r_framedata_mem_s
4332 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4333 size_t size; // how much usable space
4334 size_t current; // how much space in use
4335 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4336 size_t wantedsize; // how much space was allocated
4337 unsigned char *data; // start of real data (16byte aligned)
4341 static r_framedata_mem_t *r_framedata_mem;
4343 void R_FrameData_Reset(void)
4345 while (r_framedata_mem)
4347 r_framedata_mem_t *next = r_framedata_mem->purge;
4348 Mem_Free(r_framedata_mem);
4349 r_framedata_mem = next;
4353 void R_FrameData_Resize(void)
4356 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4357 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4358 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4360 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4361 newmem->wantedsize = wantedsize;
4362 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4363 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4364 newmem->current = 0;
4366 newmem->purge = r_framedata_mem;
4367 r_framedata_mem = newmem;
4371 void R_FrameData_NewFrame(void)
4373 R_FrameData_Resize();
4374 if (!r_framedata_mem)
4376 // if we ran out of space on the last frame, free the old memory now
4377 while (r_framedata_mem->purge)
4379 // repeatedly remove the second item in the list, leaving only head
4380 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4381 Mem_Free(r_framedata_mem->purge);
4382 r_framedata_mem->purge = next;
4384 // reset the current mem pointer
4385 r_framedata_mem->current = 0;
4386 r_framedata_mem->mark = 0;
4389 void *R_FrameData_Alloc(size_t size)
4393 // align to 16 byte boundary - the data pointer is already aligned, so we
4394 // only need to ensure the size of every allocation is also aligned
4395 size = (size + 15) & ~15;
4397 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4399 // emergency - we ran out of space, allocate more memory
4400 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4401 R_FrameData_Resize();
4404 data = r_framedata_mem->data + r_framedata_mem->current;
4405 r_framedata_mem->current += size;
4407 // count the usage for stats
4408 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4409 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4411 return (void *)data;
4414 void *R_FrameData_Store(size_t size, void *data)
4416 void *d = R_FrameData_Alloc(size);
4418 memcpy(d, data, size);
4422 void R_FrameData_SetMark(void)
4424 if (!r_framedata_mem)
4426 r_framedata_mem->mark = r_framedata_mem->current;
4429 void R_FrameData_ReturnToMark(void)
4431 if (!r_framedata_mem)
4433 r_framedata_mem->current = r_framedata_mem->mark;
4436 //==================================================================================
4438 // LordHavoc: animcache originally written by Echon, rewritten since then
4441 * Animation cache prevents re-generating mesh data for an animated model
4442 * multiple times in one frame for lighting, shadowing, reflections, etc.
4445 void R_AnimCache_Free(void)
4449 void R_AnimCache_ClearCache(void)
4452 entity_render_t *ent;
4454 for (i = 0;i < r_refdef.scene.numentities;i++)
4456 ent = r_refdef.scene.entities[i];
4457 ent->animcache_vertex3f = NULL;
4458 ent->animcache_normal3f = NULL;
4459 ent->animcache_svector3f = NULL;
4460 ent->animcache_tvector3f = NULL;
4461 ent->animcache_vertexmesh = NULL;
4462 ent->animcache_vertex3fbuffer = NULL;
4463 ent->animcache_vertexmeshbuffer = NULL;
4467 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4471 // check if we need the meshbuffers
4472 if (!vid.useinterleavedarrays)
4475 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4476 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4477 // TODO: upload vertex3f buffer?
4478 if (ent->animcache_vertexmesh)
4480 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4481 for (i = 0;i < numvertices;i++)
4482 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4483 if (ent->animcache_svector3f)
4484 for (i = 0;i < numvertices;i++)
4485 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4486 if (ent->animcache_tvector3f)
4487 for (i = 0;i < numvertices;i++)
4488 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4489 if (ent->animcache_normal3f)
4490 for (i = 0;i < numvertices;i++)
4491 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4492 // TODO: upload vertexmeshbuffer?
4496 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4498 dp_model_t *model = ent->model;
4500 // see if it's already cached this frame
4501 if (ent->animcache_vertex3f)
4503 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4504 if (wantnormals || wanttangents)
4506 if (ent->animcache_normal3f)
4507 wantnormals = false;
4508 if (ent->animcache_svector3f)
4509 wanttangents = false;
4510 if (wantnormals || wanttangents)
4512 numvertices = model->surfmesh.num_vertices;
4514 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4517 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4518 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4520 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4521 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4527 // see if this ent is worth caching
4528 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4530 // get some memory for this entity and generate mesh data
4531 numvertices = model->surfmesh.num_vertices;
4532 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4534 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4537 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4538 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4540 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4541 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4546 void R_AnimCache_CacheVisibleEntities(void)
4549 qboolean wantnormals = true;
4550 qboolean wanttangents = !r_showsurfaces.integer;
4552 switch(vid.renderpath)
4554 case RENDERPATH_GL20:
4555 case RENDERPATH_D3D9:
4556 case RENDERPATH_D3D10:
4557 case RENDERPATH_D3D11:
4558 case RENDERPATH_GLES2:
4560 case RENDERPATH_GL13:
4561 case RENDERPATH_GL11:
4562 wanttangents = false;
4564 case RENDERPATH_SOFT:
4568 if (r_shownormals.integer)
4569 wanttangents = wantnormals = true;
4571 // TODO: thread this
4572 // NOTE: R_PrepareRTLights() also caches entities
4574 for (i = 0;i < r_refdef.scene.numentities;i++)
4575 if (r_refdef.viewcache.entityvisible[i])
4576 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4579 //==================================================================================
4581 static void R_View_UpdateEntityLighting (void)
4584 entity_render_t *ent;
4585 vec3_t tempdiffusenormal, avg;
4586 vec_t f, fa, fd, fdd;
4587 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4589 for (i = 0;i < r_refdef.scene.numentities;i++)
4591 ent = r_refdef.scene.entities[i];
4593 // skip unseen models
4594 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4598 if (ent->model && ent->model->brush.num_leafs)
4600 // TODO: use modellight for r_ambient settings on world?
4601 VectorSet(ent->modellight_ambient, 0, 0, 0);
4602 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4603 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4607 // fetch the lighting from the worldmodel data
4608 VectorClear(ent->modellight_ambient);
4609 VectorClear(ent->modellight_diffuse);
4610 VectorClear(tempdiffusenormal);
4611 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4614 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4616 // complete lightning for lit sprites
4617 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4618 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4620 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4621 org[2] = org[2] + r_overheadsprites_pushback.value;
4622 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4625 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4627 if(ent->flags & RENDER_EQUALIZE)
4629 // first fix up ambient lighting...
4630 if(r_equalize_entities_minambient.value > 0)
4632 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4635 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4636 if(fa < r_equalize_entities_minambient.value * fd)
4639 // fa'/fd' = minambient
4640 // fa'+0.25*fd' = fa+0.25*fd
4642 // fa' = fd' * minambient
4643 // fd'*(0.25+minambient) = fa+0.25*fd
4645 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4646 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4648 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4649 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
4650 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4651 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4656 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4658 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4659 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4663 // adjust brightness and saturation to target
4664 avg[0] = avg[1] = avg[2] = fa / f;
4665 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4666 avg[0] = avg[1] = avg[2] = fd / f;
4667 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4673 VectorSet(ent->modellight_ambient, 1, 1, 1);
4675 // move the light direction into modelspace coordinates for lighting code
4676 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4677 if(VectorLength2(ent->modellight_lightdir) == 0)
4678 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4679 VectorNormalize(ent->modellight_lightdir);
4683 #define MAX_LINEOFSIGHTTRACES 64
4685 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4688 vec3_t boxmins, boxmaxs;
4691 dp_model_t *model = r_refdef.scene.worldmodel;
4693 if (!model || !model->brush.TraceLineOfSight)
4696 // expand the box a little
4697 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4698 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4699 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4700 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4701 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4702 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4704 // return true if eye is inside enlarged box
4705 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4709 VectorCopy(eye, start);
4710 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4711 if (model->brush.TraceLineOfSight(model, start, end))
4714 // try various random positions
4715 for (i = 0;i < numsamples;i++)
4717 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4718 if (model->brush.TraceLineOfSight(model, start, end))
4726 static void R_View_UpdateEntityVisible (void)
4731 entity_render_t *ent;
4733 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4734 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4735 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4736 : RENDER_EXTERIORMODEL;
4737 if (!r_drawviewmodel.integer)
4738 renderimask |= RENDER_VIEWMODEL;
4739 if (!r_drawexteriormodel.integer)
4740 renderimask |= RENDER_EXTERIORMODEL;
4741 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4743 // worldmodel can check visibility
4744 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4745 for (i = 0;i < r_refdef.scene.numentities;i++)
4747 ent = r_refdef.scene.entities[i];
4748 if (!(ent->flags & renderimask))
4749 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)))
4750 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))
4751 r_refdef.viewcache.entityvisible[i] = true;
4753 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4754 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4756 for (i = 0;i < r_refdef.scene.numentities;i++)
4758 ent = r_refdef.scene.entities[i];
4759 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4761 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4763 continue; // temp entities do pvs only
4764 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4765 ent->last_trace_visibility = realtime;
4766 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4767 r_refdef.viewcache.entityvisible[i] = 0;
4774 // no worldmodel or it can't check visibility
4775 for (i = 0;i < r_refdef.scene.numentities;i++)
4777 ent = r_refdef.scene.entities[i];
4778 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));
4783 /// only used if skyrendermasked, and normally returns false
4784 int R_DrawBrushModelsSky (void)
4787 entity_render_t *ent;
4790 for (i = 0;i < r_refdef.scene.numentities;i++)
4792 if (!r_refdef.viewcache.entityvisible[i])
4794 ent = r_refdef.scene.entities[i];
4795 if (!ent->model || !ent->model->DrawSky)
4797 ent->model->DrawSky(ent);
4803 static void R_DrawNoModel(entity_render_t *ent);
4804 static void R_DrawModels(void)
4807 entity_render_t *ent;
4809 for (i = 0;i < r_refdef.scene.numentities;i++)
4811 if (!r_refdef.viewcache.entityvisible[i])
4813 ent = r_refdef.scene.entities[i];
4814 r_refdef.stats.entities++;
4815 if (ent->model && ent->model->Draw != NULL)
4816 ent->model->Draw(ent);
4822 static void R_DrawModelsDepth(void)
4825 entity_render_t *ent;
4827 for (i = 0;i < r_refdef.scene.numentities;i++)
4829 if (!r_refdef.viewcache.entityvisible[i])
4831 ent = r_refdef.scene.entities[i];
4832 if (ent->model && ent->model->DrawDepth != NULL)
4833 ent->model->DrawDepth(ent);
4837 static void R_DrawModelsDebug(void)
4840 entity_render_t *ent;
4842 for (i = 0;i < r_refdef.scene.numentities;i++)
4844 if (!r_refdef.viewcache.entityvisible[i])
4846 ent = r_refdef.scene.entities[i];
4847 if (ent->model && ent->model->DrawDebug != NULL)
4848 ent->model->DrawDebug(ent);
4852 static void R_DrawModelsAddWaterPlanes(void)
4855 entity_render_t *ent;
4857 for (i = 0;i < r_refdef.scene.numentities;i++)
4859 if (!r_refdef.viewcache.entityvisible[i])
4861 ent = r_refdef.scene.entities[i];
4862 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4863 ent->model->DrawAddWaterPlanes(ent);
4867 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4869 if (r_hdr_irisadaptation.integer)
4873 vec3_t diffusenormal;
4878 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4879 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4880 brightness = max(0.0000001f, brightness);
4881 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4882 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4883 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4884 current = r_hdr_irisadaptation_value.value;
4886 current = min(current + adjust, goal);
4887 else if (current > goal)
4888 current = max(current - adjust, goal);
4889 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4890 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4892 else if (r_hdr_irisadaptation_value.value != 1.0f)
4893 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4896 static void R_View_SetFrustum(const int *scissor)
4899 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4900 vec3_t forward, left, up, origin, v;
4904 // flipped x coordinates (because x points left here)
4905 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4906 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4908 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4909 switch(vid.renderpath)
4911 case RENDERPATH_D3D9:
4912 case RENDERPATH_D3D10:
4913 case RENDERPATH_D3D11:
4914 // non-flipped y coordinates
4915 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4916 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4918 case RENDERPATH_SOFT:
4919 case RENDERPATH_GL11:
4920 case RENDERPATH_GL13:
4921 case RENDERPATH_GL20:
4922 case RENDERPATH_GLES2:
4923 // non-flipped y coordinates
4924 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4925 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4930 // we can't trust r_refdef.view.forward and friends in reflected scenes
4931 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4934 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4935 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4936 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4937 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4938 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4939 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4940 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4941 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4942 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4943 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4944 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4945 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4949 zNear = r_refdef.nearclip;
4950 nudge = 1.0 - 1.0 / (1<<23);
4951 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4952 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4953 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4954 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4955 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4956 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4957 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4958 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4964 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4965 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4966 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4967 r_refdef.view.frustum[0].dist = m[15] - m[12];
4969 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4970 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4971 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4972 r_refdef.view.frustum[1].dist = m[15] + m[12];
4974 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4975 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4976 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4977 r_refdef.view.frustum[2].dist = m[15] - m[13];
4979 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4980 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4981 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4982 r_refdef.view.frustum[3].dist = m[15] + m[13];
4984 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4985 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4986 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4987 r_refdef.view.frustum[4].dist = m[15] - m[14];
4989 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4990 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4991 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4992 r_refdef.view.frustum[5].dist = m[15] + m[14];
4995 if (r_refdef.view.useperspective)
4997 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4998 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]);
4999 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]);
5000 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]);
5001 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]);
5003 // then the normals from the corners relative to origin
5004 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5005 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5006 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5007 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5009 // in a NORMAL view, forward cross left == up
5010 // in a REFLECTED view, forward cross left == down
5011 // so our cross products above need to be adjusted for a left handed coordinate system
5012 CrossProduct(forward, left, v);
5013 if(DotProduct(v, up) < 0)
5015 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5016 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5017 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5018 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5021 // Leaving those out was a mistake, those were in the old code, and they
5022 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5023 // I couldn't reproduce it after adding those normalizations. --blub
5024 VectorNormalize(r_refdef.view.frustum[0].normal);
5025 VectorNormalize(r_refdef.view.frustum[1].normal);
5026 VectorNormalize(r_refdef.view.frustum[2].normal);
5027 VectorNormalize(r_refdef.view.frustum[3].normal);
5029 // make the corners absolute
5030 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5031 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5032 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5033 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5036 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5038 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5039 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5040 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5041 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5042 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5046 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5047 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5048 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5049 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5050 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5051 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5052 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5053 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5054 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5055 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5057 r_refdef.view.numfrustumplanes = 5;
5059 if (r_refdef.view.useclipplane)
5061 r_refdef.view.numfrustumplanes = 6;
5062 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5065 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5066 PlaneClassify(r_refdef.view.frustum + i);
5068 // LordHavoc: note to all quake engine coders, Quake had a special case
5069 // for 90 degrees which assumed a square view (wrong), so I removed it,
5070 // Quake2 has it disabled as well.
5072 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5073 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5074 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5075 //PlaneClassify(&frustum[0]);
5077 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5078 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5079 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5080 //PlaneClassify(&frustum[1]);
5082 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5083 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5084 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5085 //PlaneClassify(&frustum[2]);
5087 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5088 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5089 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5090 //PlaneClassify(&frustum[3]);
5093 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5094 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5095 //PlaneClassify(&frustum[4]);
5098 void R_View_UpdateWithScissor(const int *myscissor)
5100 R_Main_ResizeViewCache();
5101 R_View_SetFrustum(myscissor);
5102 R_View_WorldVisibility(r_refdef.view.useclipplane);
5103 R_View_UpdateEntityVisible();
5104 R_View_UpdateEntityLighting();
5107 void R_View_Update(void)
5109 R_Main_ResizeViewCache();
5110 R_View_SetFrustum(NULL);
5111 R_View_WorldVisibility(r_refdef.view.useclipplane);
5112 R_View_UpdateEntityVisible();
5113 R_View_UpdateEntityLighting();
5116 void R_Mesh_SetMainRenderTargets(void)
5118 if (r_bloomstate.fbo_framebuffer)
5119 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5121 R_Mesh_ResetRenderTargets();
5124 void R_SetupView(qboolean allowwaterclippingplane)
5126 const float *customclipplane = NULL;
5128 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5130 // LordHavoc: couldn't figure out how to make this approach the
5131 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5132 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5133 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5134 dist = r_refdef.view.clipplane.dist;
5135 plane[0] = r_refdef.view.clipplane.normal[0];
5136 plane[1] = r_refdef.view.clipplane.normal[1];
5137 plane[2] = r_refdef.view.clipplane.normal[2];
5139 customclipplane = plane;
5142 if (!r_refdef.view.useperspective)
5143 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5144 else if (vid.stencil && r_useinfinitefarclip.integer)
5145 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5147 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5148 R_Mesh_SetMainRenderTargets();
5149 R_SetViewport(&r_refdef.view.viewport);
5152 void R_EntityMatrix(const matrix4x4_t *matrix)
5154 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5156 gl_modelmatrixchanged = false;
5157 gl_modelmatrix = *matrix;
5158 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5159 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5160 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5161 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5163 switch(vid.renderpath)
5165 case RENDERPATH_D3D9:
5167 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5168 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5171 case RENDERPATH_D3D10:
5172 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5174 case RENDERPATH_D3D11:
5175 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5177 case RENDERPATH_GL13:
5178 case RENDERPATH_GL11:
5179 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5181 case RENDERPATH_SOFT:
5182 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5183 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5185 case RENDERPATH_GL20:
5186 case RENDERPATH_GLES2:
5187 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5188 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5194 void R_ResetViewRendering2D(void)
5196 r_viewport_t viewport;
5199 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5200 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);
5201 R_Mesh_ResetRenderTargets();
5202 R_SetViewport(&viewport);
5203 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5204 GL_Color(1, 1, 1, 1);
5205 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5206 GL_BlendFunc(GL_ONE, GL_ZERO);
5207 GL_ScissorTest(false);
5208 GL_DepthMask(false);
5209 GL_DepthRange(0, 1);
5210 GL_DepthTest(false);
5211 GL_DepthFunc(GL_LEQUAL);
5212 R_EntityMatrix(&identitymatrix);
5213 R_Mesh_ResetTextureState();
5214 GL_PolygonOffset(0, 0);
5215 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5216 switch(vid.renderpath)
5218 case RENDERPATH_GL11:
5219 case RENDERPATH_GL13:
5220 case RENDERPATH_GL20:
5221 case RENDERPATH_GLES2:
5222 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5224 case RENDERPATH_D3D9:
5225 case RENDERPATH_D3D10:
5226 case RENDERPATH_D3D11:
5227 case RENDERPATH_SOFT:
5230 GL_CullFace(GL_NONE);
5233 void R_ResetViewRendering3D(void)
5238 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5239 GL_Color(1, 1, 1, 1);
5240 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5241 GL_BlendFunc(GL_ONE, GL_ZERO);
5242 GL_ScissorTest(true);
5244 GL_DepthRange(0, 1);
5246 GL_DepthFunc(GL_LEQUAL);
5247 R_EntityMatrix(&identitymatrix);
5248 R_Mesh_ResetTextureState();
5249 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5250 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5251 switch(vid.renderpath)
5253 case RENDERPATH_GL11:
5254 case RENDERPATH_GL13:
5255 case RENDERPATH_GL20:
5256 case RENDERPATH_GLES2:
5257 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5259 case RENDERPATH_D3D9:
5260 case RENDERPATH_D3D10:
5261 case RENDERPATH_D3D11:
5262 case RENDERPATH_SOFT:
5265 GL_CullFace(r_refdef.view.cullface_back);
5270 R_RenderView_UpdateViewVectors
5273 static void R_RenderView_UpdateViewVectors(void)
5275 // break apart the view matrix into vectors for various purposes
5276 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5277 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5278 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5279 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5280 // make an inverted copy of the view matrix for tracking sprites
5281 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5284 void R_RenderScene(void);
5285 void R_RenderWaterPlanes(void);
5287 static void R_Water_StartFrame(void)
5290 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5291 r_waterstate_waterplane_t *p;
5293 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5296 switch(vid.renderpath)
5298 case RENDERPATH_GL20:
5299 case RENDERPATH_D3D9:
5300 case RENDERPATH_D3D10:
5301 case RENDERPATH_D3D11:
5302 case RENDERPATH_SOFT:
5303 case RENDERPATH_GLES2:
5305 case RENDERPATH_GL13:
5306 case RENDERPATH_GL11:
5310 // set waterwidth and waterheight to the water resolution that will be
5311 // used (often less than the screen resolution for faster rendering)
5312 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5313 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5315 // calculate desired texture sizes
5316 // can't use water if the card does not support the texture size
5317 if (!r_water.integer || r_showsurfaces.integer)
5318 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5319 else if (vid.support.arb_texture_non_power_of_two)
5321 texturewidth = waterwidth;
5322 textureheight = waterheight;
5323 camerawidth = waterwidth;
5324 cameraheight = waterheight;
5328 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5329 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5330 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5331 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5334 // allocate textures as needed
5335 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5337 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5338 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5340 if (p->texture_refraction)
5341 R_FreeTexture(p->texture_refraction);
5342 p->texture_refraction = NULL;
5343 if (p->texture_reflection)
5344 R_FreeTexture(p->texture_reflection);
5345 p->texture_reflection = NULL;
5346 if (p->texture_camera)
5347 R_FreeTexture(p->texture_camera);
5348 p->texture_camera = NULL;
5350 memset(&r_waterstate, 0, sizeof(r_waterstate));
5351 r_waterstate.texturewidth = texturewidth;
5352 r_waterstate.textureheight = textureheight;
5353 r_waterstate.camerawidth = camerawidth;
5354 r_waterstate.cameraheight = cameraheight;
5357 if (r_waterstate.texturewidth)
5359 r_waterstate.enabled = true;
5361 // when doing a reduced render (HDR) we want to use a smaller area
5362 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5363 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5365 // set up variables that will be used in shader setup
5366 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5367 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5368 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5369 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5372 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5373 r_waterstate.numwaterplanes = 0;
5376 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5378 int triangleindex, planeindex;
5384 r_waterstate_waterplane_t *p;
5385 texture_t *t = R_GetCurrentTexture(surface->texture);
5387 // just use the first triangle with a valid normal for any decisions
5388 VectorClear(normal);
5389 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5391 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5392 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5393 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5394 TriangleNormal(vert[0], vert[1], vert[2], normal);
5395 if (VectorLength2(normal) >= 0.001)
5399 VectorCopy(normal, plane.normal);
5400 VectorNormalize(plane.normal);
5401 plane.dist = DotProduct(vert[0], plane.normal);
5402 PlaneClassify(&plane);
5403 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5405 // skip backfaces (except if nocullface is set)
5406 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5408 VectorNegate(plane.normal, plane.normal);
5410 PlaneClassify(&plane);
5414 // find a matching plane if there is one
5415 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5416 if(p->camera_entity == t->camera_entity)
5417 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5419 if (planeindex >= r_waterstate.maxwaterplanes)
5420 return; // nothing we can do, out of planes
5422 // if this triangle does not fit any known plane rendered this frame, add one
5423 if (planeindex >= r_waterstate.numwaterplanes)
5425 // store the new plane
5426 r_waterstate.numwaterplanes++;
5428 // clear materialflags and pvs
5429 p->materialflags = 0;
5430 p->pvsvalid = false;
5431 p->camera_entity = t->camera_entity;
5432 VectorCopy(surface->mins, p->mins);
5433 VectorCopy(surface->maxs, p->maxs);
5438 p->mins[0] = min(p->mins[0], surface->mins[0]);
5439 p->mins[1] = min(p->mins[1], surface->mins[1]);
5440 p->mins[2] = min(p->mins[2], surface->mins[2]);
5441 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5442 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5443 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5445 // merge this surface's materialflags into the waterplane
5446 p->materialflags |= t->currentmaterialflags;
5447 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5449 // merge this surface's PVS into the waterplane
5450 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5451 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5452 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5454 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5460 static void R_Water_ProcessPlanes(void)
5463 r_refdef_view_t originalview;
5464 r_refdef_view_t myview;
5466 r_waterstate_waterplane_t *p;
5469 originalview = r_refdef.view;
5471 // make sure enough textures are allocated
5472 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5474 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5476 if (!p->texture_refraction)
5477 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);
5478 if (!p->texture_refraction)
5481 else if (p->materialflags & MATERIALFLAG_CAMERA)
5483 if (!p->texture_camera)
5484 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);
5485 if (!p->texture_camera)
5489 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5491 if (!p->texture_reflection)
5492 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);
5493 if (!p->texture_reflection)
5499 r_refdef.view = originalview;
5500 r_refdef.view.showdebug = false;
5501 r_refdef.view.width = r_waterstate.waterwidth;
5502 r_refdef.view.height = r_waterstate.waterheight;
5503 r_refdef.view.useclipplane = true;
5504 myview = r_refdef.view;
5505 r_waterstate.renderingscene = true;
5506 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5508 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5510 r_refdef.view = myview;
5511 if(r_water_scissormode.integer)
5514 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5515 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5518 // render reflected scene and copy into texture
5519 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5520 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5521 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5522 r_refdef.view.clipplane = p->plane;
5524 // reverse the cullface settings for this render
5525 r_refdef.view.cullface_front = GL_FRONT;
5526 r_refdef.view.cullface_back = GL_BACK;
5527 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5529 r_refdef.view.usecustompvs = true;
5531 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5533 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5536 R_ResetViewRendering3D();
5537 R_ClearScreen(r_refdef.fogenabled);
5538 if(r_water_scissormode.integer & 2)
5539 R_View_UpdateWithScissor(myscissor);
5542 if(r_water_scissormode.integer & 1)
5543 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5546 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);
5549 // render the normal view scene and copy into texture
5550 // (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)
5551 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5553 r_refdef.view = myview;
5554 if(r_water_scissormode.integer)
5557 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5558 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5561 r_waterstate.renderingrefraction = true;
5563 r_refdef.view.clipplane = p->plane;
5564 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5565 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5567 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5569 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5570 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5571 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5572 R_RenderView_UpdateViewVectors();
5573 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5575 r_refdef.view.usecustompvs = true;
5576 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);
5580 PlaneClassify(&r_refdef.view.clipplane);
5582 R_ResetViewRendering3D();
5583 R_ClearScreen(r_refdef.fogenabled);
5584 if(r_water_scissormode.integer & 2)
5585 R_View_UpdateWithScissor(myscissor);
5588 if(r_water_scissormode.integer & 1)
5589 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5592 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);
5593 r_waterstate.renderingrefraction = false;
5595 else if (p->materialflags & MATERIALFLAG_CAMERA)
5597 r_refdef.view = myview;
5599 r_refdef.view.clipplane = p->plane;
5600 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5601 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5603 r_refdef.view.width = r_waterstate.camerawidth;
5604 r_refdef.view.height = r_waterstate.cameraheight;
5605 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5606 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5608 if(p->camera_entity)
5610 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5611 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5614 // note: all of the view is used for displaying... so
5615 // there is no use in scissoring
5617 // reverse the cullface settings for this render
5618 r_refdef.view.cullface_front = GL_FRONT;
5619 r_refdef.view.cullface_back = GL_BACK;
5620 // also reverse the view matrix
5621 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
5622 R_RenderView_UpdateViewVectors();
5623 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5625 r_refdef.view.usecustompvs = true;
5626 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);
5629 // camera needs no clipplane
5630 r_refdef.view.useclipplane = false;
5632 PlaneClassify(&r_refdef.view.clipplane);
5634 R_ResetViewRendering3D();
5635 R_ClearScreen(r_refdef.fogenabled);
5639 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);
5640 r_waterstate.renderingrefraction = false;
5644 r_waterstate.renderingscene = false;
5645 r_refdef.view = originalview;
5646 R_ResetViewRendering3D();
5647 R_ClearScreen(r_refdef.fogenabled);
5651 r_refdef.view = originalview;
5652 r_waterstate.renderingscene = false;
5653 Cvar_SetValueQuick(&r_water, 0);
5654 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5658 void R_Bloom_StartFrame(void)
5660 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5663 switch(vid.renderpath)
5665 case RENDERPATH_GL20:
5666 case RENDERPATH_D3D9:
5667 case RENDERPATH_D3D10:
5668 case RENDERPATH_D3D11:
5669 case RENDERPATH_SOFT:
5670 case RENDERPATH_GLES2:
5672 case RENDERPATH_GL13:
5673 case RENDERPATH_GL11:
5677 // set bloomwidth and bloomheight to the bloom resolution that will be
5678 // used (often less than the screen resolution for faster rendering)
5679 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5680 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5681 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5682 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5683 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5685 // calculate desired texture sizes
5686 if (vid.support.arb_texture_non_power_of_two)
5688 screentexturewidth = r_refdef.view.width;
5689 screentextureheight = r_refdef.view.height;
5690 bloomtexturewidth = r_bloomstate.bloomwidth;
5691 bloomtextureheight = r_bloomstate.bloomheight;
5695 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5696 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5697 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5698 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5701 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))
5703 Cvar_SetValueQuick(&r_hdr, 0);
5704 Cvar_SetValueQuick(&r_bloom, 0);
5705 Cvar_SetValueQuick(&r_motionblur, 0);
5706 Cvar_SetValueQuick(&r_damageblur, 0);
5709 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)
5710 screentexturewidth = screentextureheight = 0;
5711 if (!r_hdr.integer && !r_bloom.integer)
5712 bloomtexturewidth = bloomtextureheight = 0;
5714 textype = TEXTYPE_COLORBUFFER;
5715 switch (vid.renderpath)
5717 case RENDERPATH_GL20:
5718 case RENDERPATH_GLES2:
5719 if (vid.support.ext_framebuffer_object)
5721 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5722 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5725 case RENDERPATH_D3D9:
5726 case RENDERPATH_D3D10:
5727 case RENDERPATH_D3D11:
5728 case RENDERPATH_SOFT:
5729 case RENDERPATH_GL13:
5730 case RENDERPATH_GL11:
5734 // allocate textures as needed
5735 if (r_bloomstate.screentexturewidth != screentexturewidth
5736 || r_bloomstate.screentextureheight != screentextureheight
5737 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5738 || r_bloomstate.bloomtextureheight != bloomtextureheight
5739 || r_bloomstate.texturetype != textype
5740 || r_bloomstate.viewfbo != r_viewfbo.integer)
5742 if (r_bloomstate.texture_bloom)
5743 R_FreeTexture(r_bloomstate.texture_bloom);
5744 r_bloomstate.texture_bloom = NULL;
5745 if (r_bloomstate.texture_screen)
5746 R_FreeTexture(r_bloomstate.texture_screen);
5747 r_bloomstate.texture_screen = NULL;
5748 if (r_bloomstate.fbo_framebuffer)
5749 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5750 r_bloomstate.fbo_framebuffer = 0;
5751 if (r_bloomstate.texture_framebuffercolor)
5752 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5753 r_bloomstate.texture_framebuffercolor = NULL;
5754 if (r_bloomstate.texture_framebufferdepth)
5755 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5756 r_bloomstate.texture_framebufferdepth = NULL;
5757 r_bloomstate.screentexturewidth = screentexturewidth;
5758 r_bloomstate.screentextureheight = screentextureheight;
5759 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5760 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5761 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5763 // FIXME: choose depth bits based on a cvar
5764 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5765 r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5766 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5767 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5768 // render depth into one texture and normalmap into the other
5772 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5773 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5774 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5775 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5776 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5779 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5780 r_bloomstate.bloomtextureheight = bloomtextureheight;
5781 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5782 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);
5783 r_bloomstate.viewfbo = r_viewfbo.integer;
5784 r_bloomstate.texturetype = textype;
5787 // when doing a reduced render (HDR) we want to use a smaller area
5788 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5789 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5790 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5791 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5792 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5794 // set up a texcoord array for the full resolution screen image
5795 // (we have to keep this around to copy back during final render)
5796 r_bloomstate.screentexcoord2f[0] = 0;
5797 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5798 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5799 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5800 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5801 r_bloomstate.screentexcoord2f[5] = 0;
5802 r_bloomstate.screentexcoord2f[6] = 0;
5803 r_bloomstate.screentexcoord2f[7] = 0;
5805 // set up a texcoord array for the reduced resolution bloom image
5806 // (which will be additive blended over the screen image)
5807 r_bloomstate.bloomtexcoord2f[0] = 0;
5808 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5809 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5810 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5811 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5812 r_bloomstate.bloomtexcoord2f[5] = 0;
5813 r_bloomstate.bloomtexcoord2f[6] = 0;
5814 r_bloomstate.bloomtexcoord2f[7] = 0;
5816 switch(vid.renderpath)
5818 case RENDERPATH_GL11:
5819 case RENDERPATH_GL13:
5820 case RENDERPATH_GL20:
5821 case RENDERPATH_SOFT:
5822 case RENDERPATH_GLES2:
5824 case RENDERPATH_D3D9:
5825 case RENDERPATH_D3D10:
5826 case RENDERPATH_D3D11:
5829 for (i = 0;i < 4;i++)
5831 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5832 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5833 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5834 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5840 if (r_hdr.integer || r_bloom.integer)
5842 r_bloomstate.enabled = true;
5843 r_bloomstate.hdr = r_hdr.integer != 0;
5846 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);
5848 if (r_bloomstate.fbo_framebuffer)
5849 r_refdef.view.clear = true;
5852 void R_Bloom_CopyBloomTexture(float colorscale)
5854 r_refdef.stats.bloom++;
5856 // scale down screen texture to the bloom texture size
5858 R_Mesh_SetMainRenderTargets();
5859 R_SetViewport(&r_bloomstate.viewport);
5860 GL_BlendFunc(GL_ONE, GL_ZERO);
5861 GL_Color(colorscale, colorscale, colorscale, 1);
5862 // 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...
5863 switch(vid.renderpath)
5865 case RENDERPATH_GL11:
5866 case RENDERPATH_GL13:
5867 case RENDERPATH_GL20:
5868 case RENDERPATH_SOFT:
5869 case RENDERPATH_GLES2:
5870 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5872 case RENDERPATH_D3D9:
5873 case RENDERPATH_D3D10:
5874 case RENDERPATH_D3D11:
5875 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5878 // TODO: do boxfilter scale-down in shader?
5879 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5880 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5881 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5883 // we now have a bloom image in the framebuffer
5884 // copy it into the bloom image texture for later processing
5885 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);
5886 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5889 void R_Bloom_CopyHDRTexture(void)
5891 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);
5892 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5895 void R_Bloom_MakeTexture(void)
5898 float xoffset, yoffset, r, brighten;
5900 r_refdef.stats.bloom++;
5902 R_ResetViewRendering2D();
5904 // we have a bloom image in the framebuffer
5906 R_SetViewport(&r_bloomstate.viewport);
5908 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5911 r = bound(0, r_bloom_colorexponent.value / x, 1);
5912 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5914 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5915 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5916 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5917 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5919 // copy the vertically blurred bloom view to a texture
5920 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);
5921 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5924 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5925 brighten = r_bloom_brighten.value;
5927 brighten *= r_hdr_range.value;
5928 brighten = sqrt(brighten);
5930 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5931 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5933 for (dir = 0;dir < 2;dir++)
5935 // blend on at multiple vertical offsets to achieve a vertical blur
5936 // TODO: do offset blends using GLSL
5937 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5938 GL_BlendFunc(GL_ONE, GL_ZERO);
5939 for (x = -range;x <= range;x++)
5941 if (!dir){xoffset = 0;yoffset = x;}
5942 else {xoffset = x;yoffset = 0;}
5943 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5944 yoffset /= (float)r_bloomstate.bloomtextureheight;
5945 // compute a texcoord array with the specified x and y offset
5946 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5947 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5948 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5949 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5950 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5951 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5952 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5953 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5954 // this r value looks like a 'dot' particle, fading sharply to
5955 // black at the edges
5956 // (probably not realistic but looks good enough)
5957 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5958 //r = brighten/(range*2+1);
5959 r = brighten / (range * 2 + 1);
5961 r *= (1 - x*x/(float)(range*range));
5962 GL_Color(r, r, r, 1);
5963 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5964 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5965 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5966 GL_BlendFunc(GL_ONE, GL_ONE);
5969 // copy the vertically blurred bloom view to a texture
5970 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);
5971 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5975 void R_HDR_RenderBloomTexture(void)
5977 int oldwidth, oldheight;
5978 float oldcolorscale;
5979 qboolean oldwaterstate;
5981 oldwaterstate = r_waterstate.enabled;
5982 oldcolorscale = r_refdef.view.colorscale;
5983 oldwidth = r_refdef.view.width;
5984 oldheight = r_refdef.view.height;
5985 r_refdef.view.width = r_bloomstate.bloomwidth;
5986 r_refdef.view.height = r_bloomstate.bloomheight;
5988 if(r_hdr.integer < 2)
5989 r_waterstate.enabled = false;
5991 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5992 // TODO: add exposure compensation features
5993 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5995 r_refdef.view.showdebug = false;
5996 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5998 R_ResetViewRendering3D();
6000 R_ClearScreen(r_refdef.fogenabled);
6001 if (r_timereport_active)
6002 R_TimeReport("HDRclear");
6005 if (r_timereport_active)
6006 R_TimeReport("visibility");
6008 // only do secondary renders with HDR if r_hdr is 2 or higher
6009 r_waterstate.numwaterplanes = 0;
6010 if (r_waterstate.enabled)
6011 R_RenderWaterPlanes();
6013 r_refdef.view.showdebug = true;
6015 r_waterstate.numwaterplanes = 0;
6017 R_ResetViewRendering2D();
6019 R_Bloom_CopyHDRTexture();
6020 R_Bloom_MakeTexture();
6022 // restore the view settings
6023 r_waterstate.enabled = oldwaterstate;
6024 r_refdef.view.width = oldwidth;
6025 r_refdef.view.height = oldheight;
6026 r_refdef.view.colorscale = oldcolorscale;
6028 R_ResetViewRendering3D();
6030 R_ClearScreen(r_refdef.fogenabled);
6031 if (r_timereport_active)
6032 R_TimeReport("viewclear");
6035 static void R_BlendView(void)
6037 unsigned int permutation;
6038 float uservecs[4][4];
6040 switch (vid.renderpath)
6042 case RENDERPATH_GL20:
6043 case RENDERPATH_D3D9:
6044 case RENDERPATH_D3D10:
6045 case RENDERPATH_D3D11:
6046 case RENDERPATH_SOFT:
6047 case RENDERPATH_GLES2:
6049 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6050 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6051 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6052 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6053 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6055 if (r_bloomstate.texture_screen)
6057 // make sure the buffer is available
6058 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6060 R_ResetViewRendering2D();
6061 R_Mesh_SetMainRenderTargets();
6063 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6065 // declare variables
6067 static float avgspeed;
6069 speed = VectorLength(cl.movement_velocity);
6071 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6072 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6074 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6075 speed = bound(0, speed, 1);
6076 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6078 // calculate values into a standard alpha
6079 cl.motionbluralpha = 1 - exp(-
6081 (r_motionblur.value * speed / 80)
6083 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6086 max(0.0001, cl.time - cl.oldtime) // fps independent
6089 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6090 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6092 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6094 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6095 GL_Color(1, 1, 1, cl.motionbluralpha);
6096 switch(vid.renderpath)
6098 case RENDERPATH_GL11:
6099 case RENDERPATH_GL13:
6100 case RENDERPATH_GL20:
6101 case RENDERPATH_SOFT:
6102 case RENDERPATH_GLES2:
6103 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6105 case RENDERPATH_D3D9:
6106 case RENDERPATH_D3D10:
6107 case RENDERPATH_D3D11:
6108 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6111 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6112 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6113 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6117 // copy view into the screen texture
6118 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);
6119 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6121 else if (!r_bloomstate.texture_bloom)
6123 // we may still have to do view tint...
6124 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6126 // apply a color tint to the whole view
6127 R_ResetViewRendering2D();
6128 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6129 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6130 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6131 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6132 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6134 break; // no screen processing, no bloom, skip it
6137 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6139 // render simple bloom effect
6140 // copy the screen and shrink it and darken it for the bloom process
6141 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6142 // make the bloom texture
6143 R_Bloom_MakeTexture();
6146 #if _MSC_VER >= 1400
6147 #define sscanf sscanf_s
6149 memset(uservecs, 0, sizeof(uservecs));
6150 if (r_glsl_postprocess_uservec1_enable.integer)
6151 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6152 if (r_glsl_postprocess_uservec2_enable.integer)
6153 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6154 if (r_glsl_postprocess_uservec3_enable.integer)
6155 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6156 if (r_glsl_postprocess_uservec4_enable.integer)
6157 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6159 R_ResetViewRendering2D();
6160 GL_Color(1, 1, 1, 1);
6161 GL_BlendFunc(GL_ONE, GL_ZERO);
6163 switch(vid.renderpath)
6165 case RENDERPATH_GL20:
6166 case RENDERPATH_GLES2:
6167 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6168 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6169 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6170 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6171 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6172 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]);
6173 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6174 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]);
6175 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]);
6176 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]);
6177 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]);
6178 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6179 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6180 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);
6182 case RENDERPATH_D3D9:
6184 // 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...
6185 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6186 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6187 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6188 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6189 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6190 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6191 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6192 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6193 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6194 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6195 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6196 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6197 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6198 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6201 case RENDERPATH_D3D10:
6202 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6204 case RENDERPATH_D3D11:
6205 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6207 case RENDERPATH_SOFT:
6208 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6209 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6210 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6211 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6212 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6213 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6214 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6215 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6216 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6217 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6218 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6219 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6220 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6221 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6226 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6227 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6229 case RENDERPATH_GL13:
6230 case RENDERPATH_GL11:
6231 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6233 // apply a color tint to the whole view
6234 R_ResetViewRendering2D();
6235 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6236 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6237 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6238 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6239 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6245 matrix4x4_t r_waterscrollmatrix;
6247 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6249 if (r_refdef.fog_density)
6251 r_refdef.fogcolor[0] = r_refdef.fog_red;
6252 r_refdef.fogcolor[1] = r_refdef.fog_green;
6253 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6255 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6256 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6257 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6258 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6262 VectorCopy(r_refdef.fogcolor, fogvec);
6263 // color.rgb *= ContrastBoost * SceneBrightness;
6264 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6265 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6266 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6267 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6272 void R_UpdateVariables(void)
6276 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6278 r_refdef.farclip = r_farclip_base.value;
6279 if (r_refdef.scene.worldmodel)
6280 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6281 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6283 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6284 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6285 r_refdef.polygonfactor = 0;
6286 r_refdef.polygonoffset = 0;
6287 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6288 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6290 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6291 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6292 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6293 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6294 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6295 if (FAKELIGHT_ENABLED)
6297 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6299 if (r_showsurfaces.integer)
6301 r_refdef.scene.rtworld = false;
6302 r_refdef.scene.rtworldshadows = false;
6303 r_refdef.scene.rtdlight = false;
6304 r_refdef.scene.rtdlightshadows = false;
6305 r_refdef.lightmapintensity = 0;
6308 if (gamemode == GAME_NEHAHRA)
6310 if (gl_fogenable.integer)
6312 r_refdef.oldgl_fogenable = true;
6313 r_refdef.fog_density = gl_fogdensity.value;
6314 r_refdef.fog_red = gl_fogred.value;
6315 r_refdef.fog_green = gl_foggreen.value;
6316 r_refdef.fog_blue = gl_fogblue.value;
6317 r_refdef.fog_alpha = 1;
6318 r_refdef.fog_start = 0;
6319 r_refdef.fog_end = gl_skyclip.value;
6320 r_refdef.fog_height = 1<<30;
6321 r_refdef.fog_fadedepth = 128;
6323 else if (r_refdef.oldgl_fogenable)
6325 r_refdef.oldgl_fogenable = false;
6326 r_refdef.fog_density = 0;
6327 r_refdef.fog_red = 0;
6328 r_refdef.fog_green = 0;
6329 r_refdef.fog_blue = 0;
6330 r_refdef.fog_alpha = 0;
6331 r_refdef.fog_start = 0;
6332 r_refdef.fog_end = 0;
6333 r_refdef.fog_height = 1<<30;
6334 r_refdef.fog_fadedepth = 128;
6338 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6339 r_refdef.fog_start = max(0, r_refdef.fog_start);
6340 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6342 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6344 if (r_refdef.fog_density && r_drawfog.integer)
6346 r_refdef.fogenabled = true;
6347 // this is the point where the fog reaches 0.9986 alpha, which we
6348 // consider a good enough cutoff point for the texture
6349 // (0.9986 * 256 == 255.6)
6350 if (r_fog_exp2.integer)
6351 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6353 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6354 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6355 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6356 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6357 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6358 R_BuildFogHeightTexture();
6359 // fog color was already set
6360 // update the fog texture
6361 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)
6362 R_BuildFogTexture();
6363 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6364 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6367 r_refdef.fogenabled = false;
6369 switch(vid.renderpath)
6371 case RENDERPATH_GL20:
6372 case RENDERPATH_D3D9:
6373 case RENDERPATH_D3D10:
6374 case RENDERPATH_D3D11:
6375 case RENDERPATH_SOFT:
6376 case RENDERPATH_GLES2:
6377 if(v_glslgamma.integer && !vid_gammatables_trivial)
6379 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6381 // build GLSL gamma texture
6382 #define RAMPWIDTH 256
6383 unsigned short ramp[RAMPWIDTH * 3];
6384 unsigned char rampbgr[RAMPWIDTH][4];
6387 r_texture_gammaramps_serial = vid_gammatables_serial;
6389 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6390 for(i = 0; i < RAMPWIDTH; ++i)
6392 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6393 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6394 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6397 if (r_texture_gammaramps)
6399 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6403 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6409 // remove GLSL gamma texture
6412 case RENDERPATH_GL13:
6413 case RENDERPATH_GL11:
6418 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6419 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6425 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6426 if( scenetype != r_currentscenetype ) {
6427 // store the old scenetype
6428 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6429 r_currentscenetype = scenetype;
6430 // move in the new scene
6431 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6440 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6442 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6443 if( scenetype == r_currentscenetype ) {
6444 return &r_refdef.scene;
6446 return &r_scenes_store[ scenetype ];
6455 int dpsoftrast_test;
6456 void R_RenderView(void)
6458 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6460 dpsoftrast_test = r_test.integer;
6462 if (r_timereport_active)
6463 R_TimeReport("start");
6464 r_textureframe++; // used only by R_GetCurrentTexture
6465 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6467 if(R_CompileShader_CheckStaticParms())
6470 if (!r_drawentities.integer)
6471 r_refdef.scene.numentities = 0;
6473 R_AnimCache_ClearCache();
6474 R_FrameData_NewFrame();
6476 /* adjust for stereo display */
6477 if(R_Stereo_Active())
6479 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);
6480 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6483 if (r_refdef.view.isoverlay)
6485 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6486 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6487 R_TimeReport("depthclear");
6489 r_refdef.view.showdebug = false;
6491 r_waterstate.enabled = false;
6492 r_waterstate.numwaterplanes = 0;
6496 r_refdef.view.matrix = originalmatrix;
6502 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6504 r_refdef.view.matrix = originalmatrix;
6505 return; //Host_Error ("R_RenderView: NULL worldmodel");
6508 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6510 R_RenderView_UpdateViewVectors();
6512 R_Shadow_UpdateWorldLightSelection();
6514 R_Bloom_StartFrame();
6515 R_Water_StartFrame();
6518 if (r_timereport_active)
6519 R_TimeReport("viewsetup");
6521 R_ResetViewRendering3D();
6523 if (r_refdef.view.clear || r_refdef.fogenabled)
6525 R_ClearScreen(r_refdef.fogenabled);
6526 if (r_timereport_active)
6527 R_TimeReport("viewclear");
6529 r_refdef.view.clear = true;
6531 // this produces a bloom texture to be used in R_BlendView() later
6532 if (r_hdr.integer && r_bloomstate.bloomwidth)
6534 R_HDR_RenderBloomTexture();
6535 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6536 r_textureframe++; // used only by R_GetCurrentTexture
6539 r_refdef.view.showdebug = true;
6542 if (r_timereport_active)
6543 R_TimeReport("visibility");
6545 r_waterstate.numwaterplanes = 0;
6546 if (r_waterstate.enabled)
6547 R_RenderWaterPlanes();
6550 r_waterstate.numwaterplanes = 0;
6553 if (r_timereport_active)
6554 R_TimeReport("blendview");
6556 GL_Scissor(0, 0, vid.width, vid.height);
6557 GL_ScissorTest(false);
6559 r_refdef.view.matrix = originalmatrix;
6564 void R_RenderWaterPlanes(void)
6566 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6568 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6569 if (r_timereport_active)
6570 R_TimeReport("waterworld");
6573 // don't let sound skip if going slow
6574 if (r_refdef.scene.extraupdate)
6577 R_DrawModelsAddWaterPlanes();
6578 if (r_timereport_active)
6579 R_TimeReport("watermodels");
6581 if (r_waterstate.numwaterplanes)
6583 R_Water_ProcessPlanes();
6584 if (r_timereport_active)
6585 R_TimeReport("waterscenes");
6589 extern void R_DrawLightningBeams (void);
6590 extern void VM_CL_AddPolygonsToMeshQueue (void);
6591 extern void R_DrawPortals (void);
6592 extern cvar_t cl_locs_show;
6593 static void R_DrawLocs(void);
6594 static void R_DrawEntityBBoxes(void);
6595 static void R_DrawModelDecals(void);
6596 extern void R_DrawModelShadows(void);
6597 extern void R_DrawModelShadowMaps(void);
6598 extern cvar_t cl_decals_newsystem;
6599 extern qboolean r_shadow_usingdeferredprepass;
6600 void R_RenderScene(void)
6602 qboolean shadowmapping = false;
6604 if (r_timereport_active)
6605 R_TimeReport("beginscene");
6607 r_refdef.stats.renders++;
6611 // don't let sound skip if going slow
6612 if (r_refdef.scene.extraupdate)
6615 R_MeshQueue_BeginScene();
6619 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);
6621 if (r_timereport_active)
6622 R_TimeReport("skystartframe");
6624 if (cl.csqc_vidvars.drawworld)
6626 // don't let sound skip if going slow
6627 if (r_refdef.scene.extraupdate)
6630 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6632 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6633 if (r_timereport_active)
6634 R_TimeReport("worldsky");
6637 if (R_DrawBrushModelsSky() && r_timereport_active)
6638 R_TimeReport("bmodelsky");
6640 if (skyrendermasked && skyrenderlater)
6642 // we have to force off the water clipping plane while rendering sky
6646 if (r_timereport_active)
6647 R_TimeReport("sky");
6651 R_AnimCache_CacheVisibleEntities();
6652 if (r_timereport_active)
6653 R_TimeReport("animation");
6655 R_Shadow_PrepareLights();
6656 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6657 R_Shadow_PrepareModelShadows();
6658 if (r_timereport_active)
6659 R_TimeReport("preparelights");
6661 if (R_Shadow_ShadowMappingEnabled())
6662 shadowmapping = true;
6664 if (r_shadow_usingdeferredprepass)
6665 R_Shadow_DrawPrepass();
6667 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6669 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6670 if (r_timereport_active)
6671 R_TimeReport("worlddepth");
6673 if (r_depthfirst.integer >= 2)
6675 R_DrawModelsDepth();
6676 if (r_timereport_active)
6677 R_TimeReport("modeldepth");
6680 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6682 R_DrawModelShadowMaps();
6683 R_ResetViewRendering3D();
6684 // don't let sound skip if going slow
6685 if (r_refdef.scene.extraupdate)
6689 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6691 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6692 if (r_timereport_active)
6693 R_TimeReport("world");
6696 // don't let sound skip if going slow
6697 if (r_refdef.scene.extraupdate)
6701 if (r_timereport_active)
6702 R_TimeReport("models");
6704 // don't let sound skip if going slow
6705 if (r_refdef.scene.extraupdate)
6708 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6710 R_DrawModelShadows();
6711 R_ResetViewRendering3D();
6712 // don't let sound skip if going slow
6713 if (r_refdef.scene.extraupdate)
6717 if (!r_shadow_usingdeferredprepass)
6719 R_Shadow_DrawLights();
6720 if (r_timereport_active)
6721 R_TimeReport("rtlights");
6724 // don't let sound skip if going slow
6725 if (r_refdef.scene.extraupdate)
6728 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6730 R_DrawModelShadows();
6731 R_ResetViewRendering3D();
6732 // don't let sound skip if going slow
6733 if (r_refdef.scene.extraupdate)
6737 if (cl.csqc_vidvars.drawworld)
6739 if (cl_decals_newsystem.integer)
6741 R_DrawModelDecals();
6742 if (r_timereport_active)
6743 R_TimeReport("modeldecals");
6748 if (r_timereport_active)
6749 R_TimeReport("decals");
6753 if (r_timereport_active)
6754 R_TimeReport("particles");
6757 if (r_timereport_active)
6758 R_TimeReport("explosions");
6760 R_DrawLightningBeams();
6761 if (r_timereport_active)
6762 R_TimeReport("lightning");
6765 VM_CL_AddPolygonsToMeshQueue();
6767 if (r_refdef.view.showdebug)
6769 if (cl_locs_show.integer)
6772 if (r_timereport_active)
6773 R_TimeReport("showlocs");
6776 if (r_drawportals.integer)
6779 if (r_timereport_active)
6780 R_TimeReport("portals");
6783 if (r_showbboxes.value > 0)
6785 R_DrawEntityBBoxes();
6786 if (r_timereport_active)
6787 R_TimeReport("bboxes");
6791 R_MeshQueue_RenderTransparent();
6792 if (r_timereport_active)
6793 R_TimeReport("drawtrans");
6795 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))
6797 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6798 if (r_timereport_active)
6799 R_TimeReport("worlddebug");
6800 R_DrawModelsDebug();
6801 if (r_timereport_active)
6802 R_TimeReport("modeldebug");
6805 if (cl.csqc_vidvars.drawworld)
6807 R_Shadow_DrawCoronas();
6808 if (r_timereport_active)
6809 R_TimeReport("coronas");
6814 GL_DepthTest(false);
6815 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6816 GL_Color(1, 1, 1, 1);
6817 qglBegin(GL_POLYGON);
6818 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6819 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6820 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6821 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6823 qglBegin(GL_POLYGON);
6824 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]);
6825 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]);
6826 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]);
6827 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]);
6829 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6833 // don't let sound skip if going slow
6834 if (r_refdef.scene.extraupdate)
6837 R_ResetViewRendering2D();
6840 static const unsigned short bboxelements[36] =
6850 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6853 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6855 RSurf_ActiveWorldEntity();
6857 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6858 GL_DepthMask(false);
6859 GL_DepthRange(0, 1);
6860 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6861 // R_Mesh_ResetTextureState();
6863 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6864 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6865 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6866 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6867 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6868 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6869 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6870 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6871 R_FillColors(color4f, 8, cr, cg, cb, ca);
6872 if (r_refdef.fogenabled)
6874 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6876 f1 = RSurf_FogVertex(v);
6878 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6879 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6880 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6883 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6884 R_Mesh_ResetTextureState();
6885 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6886 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6889 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6893 prvm_edict_t *edict;
6894 prvm_prog_t *prog_save = prog;
6896 // this function draws bounding boxes of server entities
6900 GL_CullFace(GL_NONE);
6901 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6905 for (i = 0;i < numsurfaces;i++)
6907 edict = PRVM_EDICT_NUM(surfacelist[i]);
6908 switch ((int)edict->fields.server->solid)
6910 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6911 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6912 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6913 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6914 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6915 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6917 color[3] *= r_showbboxes.value;
6918 color[3] = bound(0, color[3], 1);
6919 GL_DepthTest(!r_showdisabledepthtest.integer);
6920 GL_CullFace(r_refdef.view.cullface_front);
6921 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6927 static void R_DrawEntityBBoxes(void)
6930 prvm_edict_t *edict;
6932 prvm_prog_t *prog_save = prog;
6934 // this function draws bounding boxes of server entities
6940 for (i = 0;i < prog->num_edicts;i++)
6942 edict = PRVM_EDICT_NUM(i);
6943 if (edict->priv.server->free)
6945 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6946 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6948 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6950 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6951 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6957 static const int nomodelelement3i[24] =
6969 static const unsigned short nomodelelement3s[24] =
6981 static const float nomodelvertex3f[6*3] =
6991 static const float nomodelcolor4f[6*4] =
6993 0.0f, 0.0f, 0.5f, 1.0f,
6994 0.0f, 0.0f, 0.5f, 1.0f,
6995 0.0f, 0.5f, 0.0f, 1.0f,
6996 0.0f, 0.5f, 0.0f, 1.0f,
6997 0.5f, 0.0f, 0.0f, 1.0f,
6998 0.5f, 0.0f, 0.0f, 1.0f
7001 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7007 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);
7009 // this is only called once per entity so numsurfaces is always 1, and
7010 // surfacelist is always {0}, so this code does not handle batches
7012 if (rsurface.ent_flags & RENDER_ADDITIVE)
7014 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7015 GL_DepthMask(false);
7017 else if (rsurface.colormod[3] < 1)
7019 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7020 GL_DepthMask(false);
7024 GL_BlendFunc(GL_ONE, GL_ZERO);
7027 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7028 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7029 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7030 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7031 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7032 for (i = 0, c = color4f;i < 6;i++, c += 4)
7034 c[0] *= rsurface.colormod[0];
7035 c[1] *= rsurface.colormod[1];
7036 c[2] *= rsurface.colormod[2];
7037 c[3] *= rsurface.colormod[3];
7039 if (r_refdef.fogenabled)
7041 for (i = 0, c = color4f;i < 6;i++, c += 4)
7043 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7045 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7046 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7047 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7050 // R_Mesh_ResetTextureState();
7051 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7052 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7053 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7056 void R_DrawNoModel(entity_render_t *ent)
7059 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7060 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7061 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7063 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7066 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7068 vec3_t right1, right2, diff, normal;
7070 VectorSubtract (org2, org1, normal);
7072 // calculate 'right' vector for start
7073 VectorSubtract (r_refdef.view.origin, org1, diff);
7074 CrossProduct (normal, diff, right1);
7075 VectorNormalize (right1);
7077 // calculate 'right' vector for end
7078 VectorSubtract (r_refdef.view.origin, org2, diff);
7079 CrossProduct (normal, diff, right2);
7080 VectorNormalize (right2);
7082 vert[ 0] = org1[0] + width * right1[0];
7083 vert[ 1] = org1[1] + width * right1[1];
7084 vert[ 2] = org1[2] + width * right1[2];
7085 vert[ 3] = org1[0] - width * right1[0];
7086 vert[ 4] = org1[1] - width * right1[1];
7087 vert[ 5] = org1[2] - width * right1[2];
7088 vert[ 6] = org2[0] - width * right2[0];
7089 vert[ 7] = org2[1] - width * right2[1];
7090 vert[ 8] = org2[2] - width * right2[2];
7091 vert[ 9] = org2[0] + width * right2[0];
7092 vert[10] = org2[1] + width * right2[1];
7093 vert[11] = org2[2] + width * right2[2];
7096 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)
7098 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7099 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7100 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7101 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7102 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7103 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7104 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7105 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7106 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7107 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7108 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7109 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7112 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7117 VectorSet(v, x, y, z);
7118 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7119 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7121 if (i == mesh->numvertices)
7123 if (mesh->numvertices < mesh->maxvertices)
7125 VectorCopy(v, vertex3f);
7126 mesh->numvertices++;
7128 return mesh->numvertices;
7134 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7138 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7139 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7140 e = mesh->element3i + mesh->numtriangles * 3;
7141 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7143 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7144 if (mesh->numtriangles < mesh->maxtriangles)
7149 mesh->numtriangles++;
7151 element[1] = element[2];
7155 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7159 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7160 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7161 e = mesh->element3i + mesh->numtriangles * 3;
7162 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7164 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7165 if (mesh->numtriangles < mesh->maxtriangles)
7170 mesh->numtriangles++;
7172 element[1] = element[2];
7176 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7177 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7179 int planenum, planenum2;
7182 mplane_t *plane, *plane2;
7184 double temppoints[2][256*3];
7185 // figure out how large a bounding box we need to properly compute this brush
7187 for (w = 0;w < numplanes;w++)
7188 maxdist = max(maxdist, fabs(planes[w].dist));
7189 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7190 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7191 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7195 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7196 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7198 if (planenum2 == planenum)
7200 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);
7203 if (tempnumpoints < 3)
7205 // generate elements forming a triangle fan for this polygon
7206 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7210 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)
7212 texturelayer_t *layer;
7213 layer = t->currentlayers + t->currentnumlayers++;
7215 layer->depthmask = depthmask;
7216 layer->blendfunc1 = blendfunc1;
7217 layer->blendfunc2 = blendfunc2;
7218 layer->texture = texture;
7219 layer->texmatrix = *matrix;
7220 layer->color[0] = r;
7221 layer->color[1] = g;
7222 layer->color[2] = b;
7223 layer->color[3] = a;
7226 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7228 if(parms[0] == 0 && parms[1] == 0)
7230 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7231 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7236 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7239 index = parms[2] + r_refdef.scene.time * parms[3];
7240 index -= floor(index);
7241 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7244 case Q3WAVEFUNC_NONE:
7245 case Q3WAVEFUNC_NOISE:
7246 case Q3WAVEFUNC_COUNT:
7249 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7250 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7251 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7252 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7253 case Q3WAVEFUNC_TRIANGLE:
7255 f = index - floor(index);
7266 f = parms[0] + parms[1] * f;
7267 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7268 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7272 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7277 matrix4x4_t matrix, temp;
7278 switch(tcmod->tcmod)
7282 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7283 matrix = r_waterscrollmatrix;
7285 matrix = identitymatrix;
7287 case Q3TCMOD_ENTITYTRANSLATE:
7288 // this is used in Q3 to allow the gamecode to control texcoord
7289 // scrolling on the entity, which is not supported in darkplaces yet.
7290 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7292 case Q3TCMOD_ROTATE:
7293 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7294 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7295 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7298 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7300 case Q3TCMOD_SCROLL:
7301 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7303 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7304 w = (int) tcmod->parms[0];
7305 h = (int) tcmod->parms[1];
7306 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7308 idx = (int) floor(f * w * h);
7309 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7311 case Q3TCMOD_STRETCH:
7312 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7313 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7315 case Q3TCMOD_TRANSFORM:
7316 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7317 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7318 VectorSet(tcmat + 6, 0 , 0 , 1);
7319 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7320 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7322 case Q3TCMOD_TURBULENT:
7323 // this is handled in the RSurf_PrepareVertices function
7324 matrix = identitymatrix;
7328 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7331 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7333 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7334 char name[MAX_QPATH];
7335 skinframe_t *skinframe;
7336 unsigned char pixels[296*194];
7337 strlcpy(cache->name, skinname, sizeof(cache->name));
7338 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7339 if (developer_loading.integer)
7340 Con_Printf("loading %s\n", name);
7341 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7342 if (!skinframe || !skinframe->base)
7345 fs_offset_t filesize;
7347 f = FS_LoadFile(name, tempmempool, true, &filesize);
7350 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7351 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7355 cache->skinframe = skinframe;
7358 texture_t *R_GetCurrentTexture(texture_t *t)
7361 const entity_render_t *ent = rsurface.entity;
7362 dp_model_t *model = ent->model;
7363 q3shaderinfo_layer_tcmod_t *tcmod;
7365 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7366 return t->currentframe;
7367 t->update_lastrenderframe = r_textureframe;
7368 t->update_lastrenderentity = (void *)ent;
7370 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7371 t->camera_entity = ent->entitynumber;
7373 t->camera_entity = 0;
7375 // switch to an alternate material if this is a q1bsp animated material
7377 texture_t *texture = t;
7378 int s = rsurface.ent_skinnum;
7379 if ((unsigned int)s >= (unsigned int)model->numskins)
7381 if (model->skinscenes)
7383 if (model->skinscenes[s].framecount > 1)
7384 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7386 s = model->skinscenes[s].firstframe;
7389 t = t + s * model->num_surfaces;
7392 // use an alternate animation if the entity's frame is not 0,
7393 // and only if the texture has an alternate animation
7394 if (rsurface.ent_alttextures && t->anim_total[1])
7395 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7397 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7399 texture->currentframe = t;
7402 // update currentskinframe to be a qw skin or animation frame
7403 if (rsurface.ent_qwskin >= 0)
7405 i = rsurface.ent_qwskin;
7406 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7408 r_qwskincache_size = cl.maxclients;
7410 Mem_Free(r_qwskincache);
7411 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7413 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7414 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7415 t->currentskinframe = r_qwskincache[i].skinframe;
7416 if (t->currentskinframe == NULL)
7417 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7419 else if (t->numskinframes >= 2)
7420 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7421 if (t->backgroundnumskinframes >= 2)
7422 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7424 t->currentmaterialflags = t->basematerialflags;
7425 t->currentalpha = rsurface.colormod[3];
7426 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7427 t->currentalpha *= r_wateralpha.value;
7428 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7429 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7430 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7431 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7432 if (!(rsurface.ent_flags & RENDER_LIGHT))
7433 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7434 else if (FAKELIGHT_ENABLED)
7436 // no modellight if using fakelight for the map
7438 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7440 // pick a model lighting mode
7441 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7442 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7444 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7446 if (rsurface.ent_flags & RENDER_ADDITIVE)
7447 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7448 else if (t->currentalpha < 1)
7449 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7450 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7451 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7452 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7453 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7454 if (t->backgroundnumskinframes)
7455 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7456 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7458 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7459 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7462 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7463 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7464 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7466 // there is no tcmod
7467 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7469 t->currenttexmatrix = r_waterscrollmatrix;
7470 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7472 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7474 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7475 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7478 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7479 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7480 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7481 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7483 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7484 if (t->currentskinframe->qpixels)
7485 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7486 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7487 if (!t->basetexture)
7488 t->basetexture = r_texture_notexture;
7489 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7490 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7491 t->nmaptexture = t->currentskinframe->nmap;
7492 if (!t->nmaptexture)
7493 t->nmaptexture = r_texture_blanknormalmap;
7494 t->glosstexture = r_texture_black;
7495 t->glowtexture = t->currentskinframe->glow;
7496 t->fogtexture = t->currentskinframe->fog;
7497 t->reflectmasktexture = t->currentskinframe->reflect;
7498 if (t->backgroundnumskinframes)
7500 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7501 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7502 t->backgroundglosstexture = r_texture_black;
7503 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7504 if (!t->backgroundnmaptexture)
7505 t->backgroundnmaptexture = r_texture_blanknormalmap;
7509 t->backgroundbasetexture = r_texture_white;
7510 t->backgroundnmaptexture = r_texture_blanknormalmap;
7511 t->backgroundglosstexture = r_texture_black;
7512 t->backgroundglowtexture = NULL;
7514 t->specularpower = r_shadow_glossexponent.value;
7515 // TODO: store reference values for these in the texture?
7516 t->specularscale = 0;
7517 if (r_shadow_gloss.integer > 0)
7519 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7521 if (r_shadow_glossintensity.value > 0)
7523 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7524 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7525 t->specularscale = r_shadow_glossintensity.value;
7528 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7530 t->glosstexture = r_texture_white;
7531 t->backgroundglosstexture = r_texture_white;
7532 t->specularscale = r_shadow_gloss2intensity.value;
7533 t->specularpower = r_shadow_gloss2exponent.value;
7536 t->specularscale *= t->specularscalemod;
7537 t->specularpower *= t->specularpowermod;
7539 // lightmaps mode looks bad with dlights using actual texturing, so turn
7540 // off the colormap and glossmap, but leave the normalmap on as it still
7541 // accurately represents the shading involved
7542 if (gl_lightmaps.integer)
7544 t->basetexture = r_texture_grey128;
7545 t->pantstexture = r_texture_black;
7546 t->shirttexture = r_texture_black;
7547 t->nmaptexture = r_texture_blanknormalmap;
7548 t->glosstexture = r_texture_black;
7549 t->glowtexture = NULL;
7550 t->fogtexture = NULL;
7551 t->reflectmasktexture = NULL;
7552 t->backgroundbasetexture = NULL;
7553 t->backgroundnmaptexture = r_texture_blanknormalmap;
7554 t->backgroundglosstexture = r_texture_black;
7555 t->backgroundglowtexture = NULL;
7556 t->specularscale = 0;
7557 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7560 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7561 VectorClear(t->dlightcolor);
7562 t->currentnumlayers = 0;
7563 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7565 int blendfunc1, blendfunc2;
7567 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7569 blendfunc1 = GL_SRC_ALPHA;
7570 blendfunc2 = GL_ONE;
7572 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7574 blendfunc1 = GL_SRC_ALPHA;
7575 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7577 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7579 blendfunc1 = t->customblendfunc[0];
7580 blendfunc2 = t->customblendfunc[1];
7584 blendfunc1 = GL_ONE;
7585 blendfunc2 = GL_ZERO;
7587 // don't colormod evilblend textures
7588 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7589 VectorSet(t->lightmapcolor, 1, 1, 1);
7590 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7591 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7593 // fullbright is not affected by r_refdef.lightmapintensity
7594 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]);
7595 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7596 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]);
7597 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7598 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]);
7602 vec3_t ambientcolor;
7604 // set the color tint used for lights affecting this surface
7605 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7607 // q3bsp has no lightmap updates, so the lightstylevalue that
7608 // would normally be baked into the lightmap must be
7609 // applied to the color
7610 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7611 if (model->type == mod_brushq3)
7612 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7613 colorscale *= r_refdef.lightmapintensity;
7614 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7615 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7616 // basic lit geometry
7617 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]);
7618 // add pants/shirt if needed
7619 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7620 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]);
7621 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7622 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]);
7623 // now add ambient passes if needed
7624 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7626 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]);
7627 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7628 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]);
7629 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7630 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]);
7633 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7634 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]);
7635 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7637 // if this is opaque use alpha blend which will darken the earlier
7640 // if this is an alpha blended material, all the earlier passes
7641 // were darkened by fog already, so we only need to add the fog
7642 // color ontop through the fog mask texture
7644 // if this is an additive blended material, all the earlier passes
7645 // were darkened by fog already, and we should not add fog color
7646 // (because the background was not darkened, there is no fog color
7647 // that was lost behind it).
7648 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]);
7652 return t->currentframe;
7655 rsurfacestate_t rsurface;
7657 void RSurf_ActiveWorldEntity(void)
7659 dp_model_t *model = r_refdef.scene.worldmodel;
7660 //if (rsurface.entity == r_refdef.scene.worldentity)
7662 rsurface.entity = r_refdef.scene.worldentity;
7663 rsurface.skeleton = NULL;
7664 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7665 rsurface.ent_skinnum = 0;
7666 rsurface.ent_qwskin = -1;
7667 rsurface.ent_shadertime = 0;
7668 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7669 rsurface.matrix = identitymatrix;
7670 rsurface.inversematrix = identitymatrix;
7671 rsurface.matrixscale = 1;
7672 rsurface.inversematrixscale = 1;
7673 R_EntityMatrix(&identitymatrix);
7674 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7675 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7676 rsurface.fograngerecip = r_refdef.fograngerecip;
7677 rsurface.fogheightfade = r_refdef.fogheightfade;
7678 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7679 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7680 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7681 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7682 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7683 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7684 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7685 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7686 rsurface.colormod[3] = 1;
7687 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);
7688 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7689 rsurface.frameblend[0].lerp = 1;
7690 rsurface.ent_alttextures = false;
7691 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7692 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7693 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7694 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7695 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7696 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7697 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7698 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7699 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7700 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7701 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7702 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7703 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7704 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7705 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7706 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7707 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7708 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7709 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7710 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7711 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7712 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7713 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7714 rsurface.modelelement3i = model->surfmesh.data_element3i;
7715 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7716 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7717 rsurface.modelelement3s = model->surfmesh.data_element3s;
7718 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7719 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7720 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7721 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7722 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7723 rsurface.modelsurfaces = model->data_surfaces;
7724 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7725 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7726 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7727 rsurface.modelgeneratedvertex = false;
7728 rsurface.batchgeneratedvertex = false;
7729 rsurface.batchfirstvertex = 0;
7730 rsurface.batchnumvertices = 0;
7731 rsurface.batchfirsttriangle = 0;
7732 rsurface.batchnumtriangles = 0;
7733 rsurface.batchvertex3f = NULL;
7734 rsurface.batchvertex3f_vertexbuffer = NULL;
7735 rsurface.batchvertex3f_bufferoffset = 0;
7736 rsurface.batchsvector3f = NULL;
7737 rsurface.batchsvector3f_vertexbuffer = NULL;
7738 rsurface.batchsvector3f_bufferoffset = 0;
7739 rsurface.batchtvector3f = NULL;
7740 rsurface.batchtvector3f_vertexbuffer = NULL;
7741 rsurface.batchtvector3f_bufferoffset = 0;
7742 rsurface.batchnormal3f = NULL;
7743 rsurface.batchnormal3f_vertexbuffer = NULL;
7744 rsurface.batchnormal3f_bufferoffset = 0;
7745 rsurface.batchlightmapcolor4f = NULL;
7746 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7747 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7748 rsurface.batchtexcoordtexture2f = NULL;
7749 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7750 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7751 rsurface.batchtexcoordlightmap2f = NULL;
7752 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7753 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7754 rsurface.batchvertexmesh = NULL;
7755 rsurface.batchvertexmeshbuffer = NULL;
7756 rsurface.batchvertex3fbuffer = NULL;
7757 rsurface.batchelement3i = NULL;
7758 rsurface.batchelement3i_indexbuffer = NULL;
7759 rsurface.batchelement3i_bufferoffset = 0;
7760 rsurface.batchelement3s = NULL;
7761 rsurface.batchelement3s_indexbuffer = NULL;
7762 rsurface.batchelement3s_bufferoffset = 0;
7763 rsurface.passcolor4f = NULL;
7764 rsurface.passcolor4f_vertexbuffer = NULL;
7765 rsurface.passcolor4f_bufferoffset = 0;
7768 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7770 dp_model_t *model = ent->model;
7771 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7773 rsurface.entity = (entity_render_t *)ent;
7774 rsurface.skeleton = ent->skeleton;
7775 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7776 rsurface.ent_skinnum = ent->skinnum;
7777 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;
7778 rsurface.ent_shadertime = ent->shadertime;
7779 rsurface.ent_flags = ent->flags;
7780 rsurface.matrix = ent->matrix;
7781 rsurface.inversematrix = ent->inversematrix;
7782 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7783 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7784 R_EntityMatrix(&rsurface.matrix);
7785 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7786 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7787 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7788 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7789 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7790 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7791 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7792 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7793 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7794 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7795 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7796 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7797 rsurface.colormod[3] = ent->alpha;
7798 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7799 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7800 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7801 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7802 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7803 if (ent->model->brush.submodel && !prepass)
7805 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7806 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7808 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7810 if (ent->animcache_vertex3f)
7812 rsurface.modelvertex3f = ent->animcache_vertex3f;
7813 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7814 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7815 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7816 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7817 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7818 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7820 else if (wanttangents)
7822 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7823 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7824 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7825 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7826 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7827 rsurface.modelvertexmesh = NULL;
7828 rsurface.modelvertexmeshbuffer = NULL;
7829 rsurface.modelvertex3fbuffer = NULL;
7831 else if (wantnormals)
7833 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7834 rsurface.modelsvector3f = NULL;
7835 rsurface.modeltvector3f = NULL;
7836 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7837 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7838 rsurface.modelvertexmesh = NULL;
7839 rsurface.modelvertexmeshbuffer = NULL;
7840 rsurface.modelvertex3fbuffer = NULL;
7844 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7845 rsurface.modelsvector3f = NULL;
7846 rsurface.modeltvector3f = NULL;
7847 rsurface.modelnormal3f = NULL;
7848 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7849 rsurface.modelvertexmesh = NULL;
7850 rsurface.modelvertexmeshbuffer = NULL;
7851 rsurface.modelvertex3fbuffer = NULL;
7853 rsurface.modelvertex3f_vertexbuffer = 0;
7854 rsurface.modelvertex3f_bufferoffset = 0;
7855 rsurface.modelsvector3f_vertexbuffer = 0;
7856 rsurface.modelsvector3f_bufferoffset = 0;
7857 rsurface.modeltvector3f_vertexbuffer = 0;
7858 rsurface.modeltvector3f_bufferoffset = 0;
7859 rsurface.modelnormal3f_vertexbuffer = 0;
7860 rsurface.modelnormal3f_bufferoffset = 0;
7861 rsurface.modelgeneratedvertex = true;
7865 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7866 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7867 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7868 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7869 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7870 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7871 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7872 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7873 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7874 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7875 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7876 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7877 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7878 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7879 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7880 rsurface.modelgeneratedvertex = false;
7882 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7883 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7884 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7885 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7886 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7887 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7888 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7889 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7890 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7891 rsurface.modelelement3i = model->surfmesh.data_element3i;
7892 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7893 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7894 rsurface.modelelement3s = model->surfmesh.data_element3s;
7895 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7896 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7897 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7898 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7899 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7900 rsurface.modelsurfaces = model->data_surfaces;
7901 rsurface.batchgeneratedvertex = false;
7902 rsurface.batchfirstvertex = 0;
7903 rsurface.batchnumvertices = 0;
7904 rsurface.batchfirsttriangle = 0;
7905 rsurface.batchnumtriangles = 0;
7906 rsurface.batchvertex3f = NULL;
7907 rsurface.batchvertex3f_vertexbuffer = NULL;
7908 rsurface.batchvertex3f_bufferoffset = 0;
7909 rsurface.batchsvector3f = NULL;
7910 rsurface.batchsvector3f_vertexbuffer = NULL;
7911 rsurface.batchsvector3f_bufferoffset = 0;
7912 rsurface.batchtvector3f = NULL;
7913 rsurface.batchtvector3f_vertexbuffer = NULL;
7914 rsurface.batchtvector3f_bufferoffset = 0;
7915 rsurface.batchnormal3f = NULL;
7916 rsurface.batchnormal3f_vertexbuffer = NULL;
7917 rsurface.batchnormal3f_bufferoffset = 0;
7918 rsurface.batchlightmapcolor4f = NULL;
7919 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7920 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7921 rsurface.batchtexcoordtexture2f = NULL;
7922 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7923 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7924 rsurface.batchtexcoordlightmap2f = NULL;
7925 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7926 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7927 rsurface.batchvertexmesh = NULL;
7928 rsurface.batchvertexmeshbuffer = NULL;
7929 rsurface.batchvertex3fbuffer = NULL;
7930 rsurface.batchelement3i = NULL;
7931 rsurface.batchelement3i_indexbuffer = NULL;
7932 rsurface.batchelement3i_bufferoffset = 0;
7933 rsurface.batchelement3s = NULL;
7934 rsurface.batchelement3s_indexbuffer = NULL;
7935 rsurface.batchelement3s_bufferoffset = 0;
7936 rsurface.passcolor4f = NULL;
7937 rsurface.passcolor4f_vertexbuffer = NULL;
7938 rsurface.passcolor4f_bufferoffset = 0;
7941 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)
7943 rsurface.entity = r_refdef.scene.worldentity;
7944 rsurface.skeleton = NULL;
7945 rsurface.ent_skinnum = 0;
7946 rsurface.ent_qwskin = -1;
7947 rsurface.ent_shadertime = shadertime;
7948 rsurface.ent_flags = entflags;
7949 rsurface.modelnumvertices = numvertices;
7950 rsurface.modelnumtriangles = numtriangles;
7951 rsurface.matrix = *matrix;
7952 rsurface.inversematrix = *inversematrix;
7953 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7954 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7955 R_EntityMatrix(&rsurface.matrix);
7956 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7957 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7958 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7959 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7960 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7961 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7962 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7963 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7964 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7965 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7966 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7967 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7968 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);
7969 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7970 rsurface.frameblend[0].lerp = 1;
7971 rsurface.ent_alttextures = false;
7972 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7973 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7976 rsurface.modelvertex3f = (float *)vertex3f;
7977 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7978 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7979 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7981 else if (wantnormals)
7983 rsurface.modelvertex3f = (float *)vertex3f;
7984 rsurface.modelsvector3f = NULL;
7985 rsurface.modeltvector3f = NULL;
7986 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7990 rsurface.modelvertex3f = (float *)vertex3f;
7991 rsurface.modelsvector3f = NULL;
7992 rsurface.modeltvector3f = NULL;
7993 rsurface.modelnormal3f = NULL;
7995 rsurface.modelvertexmesh = NULL;
7996 rsurface.modelvertexmeshbuffer = NULL;
7997 rsurface.modelvertex3fbuffer = NULL;
7998 rsurface.modelvertex3f_vertexbuffer = 0;
7999 rsurface.modelvertex3f_bufferoffset = 0;
8000 rsurface.modelsvector3f_vertexbuffer = 0;
8001 rsurface.modelsvector3f_bufferoffset = 0;
8002 rsurface.modeltvector3f_vertexbuffer = 0;
8003 rsurface.modeltvector3f_bufferoffset = 0;
8004 rsurface.modelnormal3f_vertexbuffer = 0;
8005 rsurface.modelnormal3f_bufferoffset = 0;
8006 rsurface.modelgeneratedvertex = true;
8007 rsurface.modellightmapcolor4f = (float *)color4f;
8008 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8009 rsurface.modellightmapcolor4f_bufferoffset = 0;
8010 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8011 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8012 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8013 rsurface.modeltexcoordlightmap2f = NULL;
8014 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8015 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8016 rsurface.modelelement3i = (int *)element3i;
8017 rsurface.modelelement3i_indexbuffer = NULL;
8018 rsurface.modelelement3i_bufferoffset = 0;
8019 rsurface.modelelement3s = (unsigned short *)element3s;
8020 rsurface.modelelement3s_indexbuffer = NULL;
8021 rsurface.modelelement3s_bufferoffset = 0;
8022 rsurface.modellightmapoffsets = NULL;
8023 rsurface.modelsurfaces = NULL;
8024 rsurface.batchgeneratedvertex = false;
8025 rsurface.batchfirstvertex = 0;
8026 rsurface.batchnumvertices = 0;
8027 rsurface.batchfirsttriangle = 0;
8028 rsurface.batchnumtriangles = 0;
8029 rsurface.batchvertex3f = NULL;
8030 rsurface.batchvertex3f_vertexbuffer = NULL;
8031 rsurface.batchvertex3f_bufferoffset = 0;
8032 rsurface.batchsvector3f = NULL;
8033 rsurface.batchsvector3f_vertexbuffer = NULL;
8034 rsurface.batchsvector3f_bufferoffset = 0;
8035 rsurface.batchtvector3f = NULL;
8036 rsurface.batchtvector3f_vertexbuffer = NULL;
8037 rsurface.batchtvector3f_bufferoffset = 0;
8038 rsurface.batchnormal3f = NULL;
8039 rsurface.batchnormal3f_vertexbuffer = NULL;
8040 rsurface.batchnormal3f_bufferoffset = 0;
8041 rsurface.batchlightmapcolor4f = NULL;
8042 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8043 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8044 rsurface.batchtexcoordtexture2f = NULL;
8045 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8046 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8047 rsurface.batchtexcoordlightmap2f = NULL;
8048 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8049 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8050 rsurface.batchvertexmesh = NULL;
8051 rsurface.batchvertexmeshbuffer = NULL;
8052 rsurface.batchvertex3fbuffer = NULL;
8053 rsurface.batchelement3i = NULL;
8054 rsurface.batchelement3i_indexbuffer = NULL;
8055 rsurface.batchelement3i_bufferoffset = 0;
8056 rsurface.batchelement3s = NULL;
8057 rsurface.batchelement3s_indexbuffer = NULL;
8058 rsurface.batchelement3s_bufferoffset = 0;
8059 rsurface.passcolor4f = NULL;
8060 rsurface.passcolor4f_vertexbuffer = NULL;
8061 rsurface.passcolor4f_bufferoffset = 0;
8063 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8065 if ((wantnormals || wanttangents) && !normal3f)
8067 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8068 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8070 if (wanttangents && !svector3f)
8072 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8073 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8074 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8079 float RSurf_FogPoint(const float *v)
8081 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8082 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8083 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8084 float FogHeightFade = r_refdef.fogheightfade;
8086 unsigned int fogmasktableindex;
8087 if (r_refdef.fogplaneviewabove)
8088 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8090 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8091 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8092 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8095 float RSurf_FogVertex(const float *v)
8097 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8098 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8099 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8100 float FogHeightFade = rsurface.fogheightfade;
8102 unsigned int fogmasktableindex;
8103 if (r_refdef.fogplaneviewabove)
8104 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8106 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8107 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8108 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8111 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8114 for (i = 0;i < numelements;i++)
8115 outelement3i[i] = inelement3i[i] + adjust;
8118 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8119 extern cvar_t gl_vbo;
8120 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8128 int surfacefirsttriangle;
8129 int surfacenumtriangles;
8130 int surfacefirstvertex;
8131 int surfaceendvertex;
8132 int surfacenumvertices;
8133 int batchnumvertices;
8134 int batchnumtriangles;
8138 qboolean dynamicvertex;
8142 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8144 q3shaderinfo_deform_t *deform;
8145 const msurface_t *surface, *firstsurface;
8146 r_vertexmesh_t *vertexmesh;
8147 if (!texturenumsurfaces)
8149 // find vertex range of this surface batch
8151 firstsurface = texturesurfacelist[0];
8152 firsttriangle = firstsurface->num_firsttriangle;
8153 batchnumvertices = 0;
8154 batchnumtriangles = 0;
8155 firstvertex = endvertex = firstsurface->num_firstvertex;
8156 for (i = 0;i < texturenumsurfaces;i++)
8158 surface = texturesurfacelist[i];
8159 if (surface != firstsurface + i)
8161 surfacefirstvertex = surface->num_firstvertex;
8162 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8163 surfacenumvertices = surface->num_vertices;
8164 surfacenumtriangles = surface->num_triangles;
8165 if (firstvertex > surfacefirstvertex)
8166 firstvertex = surfacefirstvertex;
8167 if (endvertex < surfaceendvertex)
8168 endvertex = surfaceendvertex;
8169 batchnumvertices += surfacenumvertices;
8170 batchnumtriangles += surfacenumtriangles;
8173 // we now know the vertex range used, and if there are any gaps in it
8174 rsurface.batchfirstvertex = firstvertex;
8175 rsurface.batchnumvertices = endvertex - firstvertex;
8176 rsurface.batchfirsttriangle = firsttriangle;
8177 rsurface.batchnumtriangles = batchnumtriangles;
8179 // this variable holds flags for which properties have been updated that
8180 // may require regenerating vertexmesh array...
8183 // check if any dynamic vertex processing must occur
8184 dynamicvertex = false;
8186 // if there is a chance of animated vertex colors, it's a dynamic batch
8187 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8189 dynamicvertex = true;
8190 batchneed |= BATCHNEED_NOGAPS;
8191 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8194 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8196 switch (deform->deform)
8199 case Q3DEFORM_PROJECTIONSHADOW:
8200 case Q3DEFORM_TEXT0:
8201 case Q3DEFORM_TEXT1:
8202 case Q3DEFORM_TEXT2:
8203 case Q3DEFORM_TEXT3:
8204 case Q3DEFORM_TEXT4:
8205 case Q3DEFORM_TEXT5:
8206 case Q3DEFORM_TEXT6:
8207 case Q3DEFORM_TEXT7:
8210 case Q3DEFORM_AUTOSPRITE:
8211 dynamicvertex = true;
8212 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8213 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8215 case Q3DEFORM_AUTOSPRITE2:
8216 dynamicvertex = true;
8217 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8218 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8220 case Q3DEFORM_NORMAL:
8221 dynamicvertex = true;
8222 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8223 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8226 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8227 break; // if wavefunc is a nop, ignore this transform
8228 dynamicvertex = true;
8229 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8230 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8232 case Q3DEFORM_BULGE:
8233 dynamicvertex = true;
8234 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8235 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8238 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8239 break; // if wavefunc is a nop, ignore this transform
8240 dynamicvertex = true;
8241 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8242 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8246 switch(rsurface.texture->tcgen.tcgen)
8249 case Q3TCGEN_TEXTURE:
8251 case Q3TCGEN_LIGHTMAP:
8252 dynamicvertex = true;
8253 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8254 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8256 case Q3TCGEN_VECTOR:
8257 dynamicvertex = true;
8258 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8259 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8261 case Q3TCGEN_ENVIRONMENT:
8262 dynamicvertex = true;
8263 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8264 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8267 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8269 dynamicvertex = true;
8270 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8271 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8274 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8276 dynamicvertex = true;
8277 batchneed |= BATCHNEED_NOGAPS;
8278 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8281 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8283 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8284 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8285 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8286 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8287 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8288 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8289 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8292 // when the model data has no vertex buffer (dynamic mesh), we need to
8294 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8295 batchneed |= BATCHNEED_NOGAPS;
8297 // if needsupdate, we have to do a dynamic vertex batch for sure
8298 if (needsupdate & batchneed)
8299 dynamicvertex = true;
8301 // see if we need to build vertexmesh from arrays
8302 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8303 dynamicvertex = true;
8305 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8306 // also some drivers strongly dislike firstvertex
8307 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8308 dynamicvertex = true;
8310 rsurface.batchvertex3f = rsurface.modelvertex3f;
8311 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8312 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8313 rsurface.batchsvector3f = rsurface.modelsvector3f;
8314 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8315 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8316 rsurface.batchtvector3f = rsurface.modeltvector3f;
8317 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8318 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8319 rsurface.batchnormal3f = rsurface.modelnormal3f;
8320 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8321 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8322 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8323 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8324 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8325 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8326 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8327 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8328 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8329 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8330 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8331 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8332 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8333 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8334 rsurface.batchelement3i = rsurface.modelelement3i;
8335 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8336 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8337 rsurface.batchelement3s = rsurface.modelelement3s;
8338 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8339 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8341 // if any dynamic vertex processing has to occur in software, we copy the
8342 // entire surface list together before processing to rebase the vertices
8343 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8345 // if any gaps exist and we do not have a static vertex buffer, we have to
8346 // copy the surface list together to avoid wasting upload bandwidth on the
8347 // vertices in the gaps.
8349 // if gaps exist and we have a static vertex buffer, we still have to
8350 // combine the index buffer ranges into one dynamic index buffer.
8352 // in all cases we end up with data that can be drawn in one call.
8356 // static vertex data, just set pointers...
8357 rsurface.batchgeneratedvertex = false;
8358 // if there are gaps, we want to build a combined index buffer,
8359 // otherwise use the original static buffer with an appropriate offset
8362 // build a new triangle elements array for this batch
8363 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8364 rsurface.batchfirsttriangle = 0;
8366 for (i = 0;i < texturenumsurfaces;i++)
8368 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8369 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8370 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8371 numtriangles += surfacenumtriangles;
8373 rsurface.batchelement3i_indexbuffer = NULL;
8374 rsurface.batchelement3i_bufferoffset = 0;
8375 rsurface.batchelement3s = NULL;
8376 rsurface.batchelement3s_indexbuffer = NULL;
8377 rsurface.batchelement3s_bufferoffset = 0;
8378 if (endvertex <= 65536)
8380 // make a 16bit (unsigned short) index array if possible
8381 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8382 for (i = 0;i < numtriangles*3;i++)
8383 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8389 // something needs software processing, do it for real...
8390 // we only directly handle separate array data in this case and then
8391 // generate interleaved data if needed...
8392 rsurface.batchgeneratedvertex = true;
8394 // now copy the vertex data into a combined array and make an index array
8395 // (this is what Quake3 does all the time)
8396 //if (gaps || rsurface.batchfirstvertex)
8398 rsurface.batchvertex3fbuffer = NULL;
8399 rsurface.batchvertexmesh = NULL;
8400 rsurface.batchvertexmeshbuffer = NULL;
8401 rsurface.batchvertex3f = NULL;
8402 rsurface.batchvertex3f_vertexbuffer = NULL;
8403 rsurface.batchvertex3f_bufferoffset = 0;
8404 rsurface.batchsvector3f = NULL;
8405 rsurface.batchsvector3f_vertexbuffer = NULL;
8406 rsurface.batchsvector3f_bufferoffset = 0;
8407 rsurface.batchtvector3f = NULL;
8408 rsurface.batchtvector3f_vertexbuffer = NULL;
8409 rsurface.batchtvector3f_bufferoffset = 0;
8410 rsurface.batchnormal3f = NULL;
8411 rsurface.batchnormal3f_vertexbuffer = NULL;
8412 rsurface.batchnormal3f_bufferoffset = 0;
8413 rsurface.batchlightmapcolor4f = NULL;
8414 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8415 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8416 rsurface.batchtexcoordtexture2f = NULL;
8417 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8418 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8419 rsurface.batchtexcoordlightmap2f = NULL;
8420 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8421 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8422 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8423 rsurface.batchelement3i_indexbuffer = NULL;
8424 rsurface.batchelement3i_bufferoffset = 0;
8425 rsurface.batchelement3s = NULL;
8426 rsurface.batchelement3s_indexbuffer = NULL;
8427 rsurface.batchelement3s_bufferoffset = 0;
8428 // we'll only be setting up certain arrays as needed
8429 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8430 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8431 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8432 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8433 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8434 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8435 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8437 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8438 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8440 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8441 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8442 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8443 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8444 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8445 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8448 for (i = 0;i < texturenumsurfaces;i++)
8450 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8451 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8452 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8453 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8454 // copy only the data requested
8455 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8456 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8457 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8459 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8460 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8461 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8462 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8463 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8465 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8466 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8468 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8469 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8470 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8471 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8472 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8473 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8475 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8476 numvertices += surfacenumvertices;
8477 numtriangles += surfacenumtriangles;
8480 // generate a 16bit index array as well if possible
8481 // (in general, dynamic batches fit)
8482 if (numvertices <= 65536)
8484 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8485 for (i = 0;i < numtriangles*3;i++)
8486 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8489 // since we've copied everything, the batch now starts at 0
8490 rsurface.batchfirstvertex = 0;
8491 rsurface.batchnumvertices = batchnumvertices;
8492 rsurface.batchfirsttriangle = 0;
8493 rsurface.batchnumtriangles = batchnumtriangles;
8496 // q1bsp surfaces rendered in vertex color mode have to have colors
8497 // calculated based on lightstyles
8498 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8500 // generate color arrays for the surfaces in this list
8505 const unsigned char *lm;
8506 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8507 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8508 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8510 for (i = 0;i < texturenumsurfaces;i++)
8512 surface = texturesurfacelist[i];
8513 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8514 surfacenumvertices = surface->num_vertices;
8515 if (surface->lightmapinfo->samples)
8517 for (j = 0;j < surfacenumvertices;j++)
8519 lm = surface->lightmapinfo->samples + offsets[j];
8520 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8521 VectorScale(lm, scale, c);
8522 if (surface->lightmapinfo->styles[1] != 255)
8524 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8526 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8527 VectorMA(c, scale, lm, c);
8528 if (surface->lightmapinfo->styles[2] != 255)
8531 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8532 VectorMA(c, scale, lm, c);
8533 if (surface->lightmapinfo->styles[3] != 255)
8536 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8537 VectorMA(c, scale, lm, c);
8544 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);
8550 for (j = 0;j < surfacenumvertices;j++)
8552 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8559 // if vertices are deformed (sprite flares and things in maps, possibly
8560 // water waves, bulges and other deformations), modify the copied vertices
8562 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8564 switch (deform->deform)
8567 case Q3DEFORM_PROJECTIONSHADOW:
8568 case Q3DEFORM_TEXT0:
8569 case Q3DEFORM_TEXT1:
8570 case Q3DEFORM_TEXT2:
8571 case Q3DEFORM_TEXT3:
8572 case Q3DEFORM_TEXT4:
8573 case Q3DEFORM_TEXT5:
8574 case Q3DEFORM_TEXT6:
8575 case Q3DEFORM_TEXT7:
8578 case Q3DEFORM_AUTOSPRITE:
8579 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8580 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8581 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8582 VectorNormalize(newforward);
8583 VectorNormalize(newright);
8584 VectorNormalize(newup);
8585 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8586 // rsurface.batchvertex3f_vertexbuffer = NULL;
8587 // rsurface.batchvertex3f_bufferoffset = 0;
8588 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8589 // rsurface.batchsvector3f_vertexbuffer = NULL;
8590 // rsurface.batchsvector3f_bufferoffset = 0;
8591 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8592 // rsurface.batchtvector3f_vertexbuffer = NULL;
8593 // rsurface.batchtvector3f_bufferoffset = 0;
8594 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8595 // rsurface.batchnormal3f_vertexbuffer = NULL;
8596 // rsurface.batchnormal3f_bufferoffset = 0;
8597 // a single autosprite surface can contain multiple sprites...
8598 for (j = 0;j < batchnumvertices - 3;j += 4)
8600 VectorClear(center);
8601 for (i = 0;i < 4;i++)
8602 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8603 VectorScale(center, 0.25f, center);
8604 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8605 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8606 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8607 for (i = 0;i < 4;i++)
8609 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8610 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8613 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8614 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8615 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);
8617 case Q3DEFORM_AUTOSPRITE2:
8618 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8619 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8620 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8621 VectorNormalize(newforward);
8622 VectorNormalize(newright);
8623 VectorNormalize(newup);
8624 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8625 // rsurface.batchvertex3f_vertexbuffer = NULL;
8626 // rsurface.batchvertex3f_bufferoffset = 0;
8628 const float *v1, *v2;
8638 memset(shortest, 0, sizeof(shortest));
8639 // a single autosprite surface can contain multiple sprites...
8640 for (j = 0;j < batchnumvertices - 3;j += 4)
8642 VectorClear(center);
8643 for (i = 0;i < 4;i++)
8644 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8645 VectorScale(center, 0.25f, center);
8646 // find the two shortest edges, then use them to define the
8647 // axis vectors for rotating around the central axis
8648 for (i = 0;i < 6;i++)
8650 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8651 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8652 l = VectorDistance2(v1, v2);
8653 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8655 l += (1.0f / 1024.0f);
8656 if (shortest[0].length2 > l || i == 0)
8658 shortest[1] = shortest[0];
8659 shortest[0].length2 = l;
8660 shortest[0].v1 = v1;
8661 shortest[0].v2 = v2;
8663 else if (shortest[1].length2 > l || i == 1)
8665 shortest[1].length2 = l;
8666 shortest[1].v1 = v1;
8667 shortest[1].v2 = v2;
8670 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8671 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8672 // this calculates the right vector from the shortest edge
8673 // and the up vector from the edge midpoints
8674 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8675 VectorNormalize(right);
8676 VectorSubtract(end, start, up);
8677 VectorNormalize(up);
8678 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8679 VectorSubtract(rsurface.localvieworigin, center, forward);
8680 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8681 VectorNegate(forward, forward);
8682 VectorReflect(forward, 0, up, forward);
8683 VectorNormalize(forward);
8684 CrossProduct(up, forward, newright);
8685 VectorNormalize(newright);
8686 // rotate the quad around the up axis vector, this is made
8687 // especially easy by the fact we know the quad is flat,
8688 // so we only have to subtract the center position and
8689 // measure distance along the right vector, and then
8690 // multiply that by the newright vector and add back the
8692 // we also need to subtract the old position to undo the
8693 // displacement from the center, which we do with a
8694 // DotProduct, the subtraction/addition of center is also
8695 // optimized into DotProducts here
8696 l = DotProduct(right, center);
8697 for (i = 0;i < 4;i++)
8699 v1 = rsurface.batchvertex3f + 3*(j+i);
8700 f = DotProduct(right, v1) - l;
8701 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8705 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8707 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8708 // rsurface.batchnormal3f_vertexbuffer = NULL;
8709 // rsurface.batchnormal3f_bufferoffset = 0;
8710 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8712 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8714 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8715 // rsurface.batchsvector3f_vertexbuffer = NULL;
8716 // rsurface.batchsvector3f_bufferoffset = 0;
8717 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8718 // rsurface.batchtvector3f_vertexbuffer = NULL;
8719 // rsurface.batchtvector3f_bufferoffset = 0;
8720 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);
8723 case Q3DEFORM_NORMAL:
8724 // deform the normals to make reflections wavey
8725 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8726 rsurface.batchnormal3f_vertexbuffer = NULL;
8727 rsurface.batchnormal3f_bufferoffset = 0;
8728 for (j = 0;j < batchnumvertices;j++)
8731 float *normal = rsurface.batchnormal3f + 3*j;
8732 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8733 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8734 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]);
8735 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]);
8736 VectorNormalize(normal);
8738 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8740 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8741 // rsurface.batchsvector3f_vertexbuffer = NULL;
8742 // rsurface.batchsvector3f_bufferoffset = 0;
8743 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8744 // rsurface.batchtvector3f_vertexbuffer = NULL;
8745 // rsurface.batchtvector3f_bufferoffset = 0;
8746 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);
8750 // deform vertex array to make wavey water and flags and such
8751 waveparms[0] = deform->waveparms[0];
8752 waveparms[1] = deform->waveparms[1];
8753 waveparms[2] = deform->waveparms[2];
8754 waveparms[3] = deform->waveparms[3];
8755 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8756 break; // if wavefunc is a nop, don't make a dynamic vertex array
8757 // this is how a divisor of vertex influence on deformation
8758 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8759 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8760 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8761 // rsurface.batchvertex3f_vertexbuffer = NULL;
8762 // rsurface.batchvertex3f_bufferoffset = 0;
8763 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8764 // rsurface.batchnormal3f_vertexbuffer = NULL;
8765 // rsurface.batchnormal3f_bufferoffset = 0;
8766 for (j = 0;j < batchnumvertices;j++)
8768 // if the wavefunc depends on time, evaluate it per-vertex
8771 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8772 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8774 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8776 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8777 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8778 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8780 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8781 // rsurface.batchsvector3f_vertexbuffer = NULL;
8782 // rsurface.batchsvector3f_bufferoffset = 0;
8783 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8784 // rsurface.batchtvector3f_vertexbuffer = NULL;
8785 // rsurface.batchtvector3f_bufferoffset = 0;
8786 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);
8789 case Q3DEFORM_BULGE:
8790 // deform vertex array to make the surface have moving bulges
8791 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8792 // rsurface.batchvertex3f_vertexbuffer = NULL;
8793 // rsurface.batchvertex3f_bufferoffset = 0;
8794 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8795 // rsurface.batchnormal3f_vertexbuffer = NULL;
8796 // rsurface.batchnormal3f_bufferoffset = 0;
8797 for (j = 0;j < batchnumvertices;j++)
8799 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8800 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8802 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8803 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8804 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8806 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8807 // rsurface.batchsvector3f_vertexbuffer = NULL;
8808 // rsurface.batchsvector3f_bufferoffset = 0;
8809 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8810 // rsurface.batchtvector3f_vertexbuffer = NULL;
8811 // rsurface.batchtvector3f_bufferoffset = 0;
8812 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);
8816 // deform vertex array
8817 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8818 break; // if wavefunc is a nop, don't make a dynamic vertex array
8819 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8820 VectorScale(deform->parms, scale, waveparms);
8821 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8822 // rsurface.batchvertex3f_vertexbuffer = NULL;
8823 // rsurface.batchvertex3f_bufferoffset = 0;
8824 for (j = 0;j < batchnumvertices;j++)
8825 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8830 // generate texcoords based on the chosen texcoord source
8831 switch(rsurface.texture->tcgen.tcgen)
8834 case Q3TCGEN_TEXTURE:
8836 case Q3TCGEN_LIGHTMAP:
8837 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8838 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8839 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8840 if (rsurface.batchtexcoordlightmap2f)
8841 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8843 case Q3TCGEN_VECTOR:
8844 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8845 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8846 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8847 for (j = 0;j < batchnumvertices;j++)
8849 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8850 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8853 case Q3TCGEN_ENVIRONMENT:
8854 // make environment reflections using a spheremap
8855 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8856 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8857 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8858 for (j = 0;j < batchnumvertices;j++)
8860 // identical to Q3A's method, but executed in worldspace so
8861 // carried models can be shiny too
8863 float viewer[3], d, reflected[3], worldreflected[3];
8865 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8866 // VectorNormalize(viewer);
8868 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8870 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8871 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8872 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8873 // note: this is proportinal to viewer, so we can normalize later
8875 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8876 VectorNormalize(worldreflected);
8878 // note: this sphere map only uses world x and z!
8879 // so positive and negative y will LOOK THE SAME.
8880 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8881 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8885 // the only tcmod that needs software vertex processing is turbulent, so
8886 // check for it here and apply the changes if needed
8887 // and we only support that as the first one
8888 // (handling a mixture of turbulent and other tcmods would be problematic
8889 // without punting it entirely to a software path)
8890 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8892 amplitude = rsurface.texture->tcmods[0].parms[1];
8893 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8894 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8895 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8896 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8897 for (j = 0;j < batchnumvertices;j++)
8899 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);
8900 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8904 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8906 // convert the modified arrays to vertex structs
8907 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8908 // rsurface.batchvertexmeshbuffer = NULL;
8909 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8910 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8911 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8912 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8913 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8914 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8915 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8917 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8919 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8920 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8923 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8924 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8925 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8926 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8927 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8928 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8929 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8930 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8931 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8935 void RSurf_DrawBatch(void)
8937 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8938 // through the pipeline, killing it earlier in the pipeline would have
8939 // per-surface overhead rather than per-batch overhead, so it's best to
8940 // reject it here, before it hits glDraw.
8941 if (rsurface.batchnumtriangles == 0)
8944 // batch debugging code
8945 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8951 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8952 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8955 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8957 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8959 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8960 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);
8967 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);
8970 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8972 // pick the closest matching water plane
8973 int planeindex, vertexindex, bestplaneindex = -1;
8977 r_waterstate_waterplane_t *p;
8978 qboolean prepared = false;
8980 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8982 if(p->camera_entity != rsurface.texture->camera_entity)
8987 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8989 if(rsurface.batchnumvertices == 0)
8992 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8994 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8995 d += fabs(PlaneDiff(vert, &p->plane));
8997 if (bestd > d || bestplaneindex < 0)
9000 bestplaneindex = planeindex;
9003 return bestplaneindex;
9004 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9005 // this situation though, as it might be better to render single larger
9006 // batches with useless stuff (backface culled for example) than to
9007 // render multiple smaller batches
9010 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9013 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9014 rsurface.passcolor4f_vertexbuffer = 0;
9015 rsurface.passcolor4f_bufferoffset = 0;
9016 for (i = 0;i < rsurface.batchnumvertices;i++)
9017 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9020 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9027 if (rsurface.passcolor4f)
9029 // generate color arrays
9030 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9031 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9032 rsurface.passcolor4f_vertexbuffer = 0;
9033 rsurface.passcolor4f_bufferoffset = 0;
9034 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)
9036 f = RSurf_FogVertex(v);
9045 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9046 rsurface.passcolor4f_vertexbuffer = 0;
9047 rsurface.passcolor4f_bufferoffset = 0;
9048 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9050 f = RSurf_FogVertex(v);
9059 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9066 if (!rsurface.passcolor4f)
9068 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9069 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9070 rsurface.passcolor4f_vertexbuffer = 0;
9071 rsurface.passcolor4f_bufferoffset = 0;
9072 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)
9074 f = RSurf_FogVertex(v);
9075 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9076 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9077 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9082 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9087 if (!rsurface.passcolor4f)
9089 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9090 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9091 rsurface.passcolor4f_vertexbuffer = 0;
9092 rsurface.passcolor4f_bufferoffset = 0;
9093 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9102 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9107 if (!rsurface.passcolor4f)
9109 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9110 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9111 rsurface.passcolor4f_vertexbuffer = 0;
9112 rsurface.passcolor4f_bufferoffset = 0;
9113 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9115 c2[0] = c[0] + r_refdef.scene.ambient;
9116 c2[1] = c[1] + r_refdef.scene.ambient;
9117 c2[2] = c[2] + r_refdef.scene.ambient;
9122 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9125 rsurface.passcolor4f = NULL;
9126 rsurface.passcolor4f_vertexbuffer = 0;
9127 rsurface.passcolor4f_bufferoffset = 0;
9128 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9129 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9130 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9131 GL_Color(r, g, b, a);
9132 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9136 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9138 // TODO: optimize applyfog && applycolor case
9139 // just apply fog if necessary, and tint the fog color array if necessary
9140 rsurface.passcolor4f = NULL;
9141 rsurface.passcolor4f_vertexbuffer = 0;
9142 rsurface.passcolor4f_bufferoffset = 0;
9143 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9144 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9145 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9146 GL_Color(r, g, b, a);
9150 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9153 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9154 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9155 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9156 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9157 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9158 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9159 GL_Color(r, g, b, a);
9163 static void RSurf_DrawBatch_GL11_ClampColor(void)
9168 if (!rsurface.passcolor4f)
9170 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9172 c2[0] = bound(0.0f, c1[0], 1.0f);
9173 c2[1] = bound(0.0f, c1[1], 1.0f);
9174 c2[2] = bound(0.0f, c1[2], 1.0f);
9175 c2[3] = bound(0.0f, c1[3], 1.0f);
9179 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9189 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9190 rsurface.passcolor4f_vertexbuffer = 0;
9191 rsurface.passcolor4f_bufferoffset = 0;
9192 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)
9194 f = -DotProduct(r_refdef.view.forward, n);
9196 f = f * 0.85 + 0.15; // work around so stuff won't get black
9197 f *= r_refdef.lightmapintensity;
9198 Vector4Set(c, f, f, f, 1);
9202 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9204 RSurf_DrawBatch_GL11_ApplyFakeLight();
9205 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9206 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9207 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9208 GL_Color(r, g, b, a);
9212 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9220 vec3_t ambientcolor;
9221 vec3_t diffusecolor;
9225 VectorCopy(rsurface.modellight_lightdir, lightdir);
9226 f = 0.5f * r_refdef.lightmapintensity;
9227 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9228 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9229 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9230 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9231 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9232 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9234 if (VectorLength2(diffusecolor) > 0)
9236 // q3-style directional shading
9237 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9238 rsurface.passcolor4f_vertexbuffer = 0;
9239 rsurface.passcolor4f_bufferoffset = 0;
9240 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)
9242 if ((f = DotProduct(n, lightdir)) > 0)
9243 VectorMA(ambientcolor, f, diffusecolor, c);
9245 VectorCopy(ambientcolor, c);
9252 *applycolor = false;
9256 *r = ambientcolor[0];
9257 *g = ambientcolor[1];
9258 *b = ambientcolor[2];
9259 rsurface.passcolor4f = NULL;
9260 rsurface.passcolor4f_vertexbuffer = 0;
9261 rsurface.passcolor4f_bufferoffset = 0;
9265 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9267 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9268 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9269 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9270 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9271 GL_Color(r, g, b, a);
9275 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9283 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9284 rsurface.passcolor4f_vertexbuffer = 0;
9285 rsurface.passcolor4f_bufferoffset = 0;
9287 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9289 f = 1 - RSurf_FogVertex(v);
9297 void RSurf_SetupDepthAndCulling(void)
9299 // submodels are biased to avoid z-fighting with world surfaces that they
9300 // may be exactly overlapping (avoids z-fighting artifacts on certain
9301 // doors and things in Quake maps)
9302 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9303 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9304 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9305 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9308 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9310 // transparent sky would be ridiculous
9311 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9313 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9314 skyrenderlater = true;
9315 RSurf_SetupDepthAndCulling();
9317 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9318 // skymasking on them, and Quake3 never did sky masking (unlike
9319 // software Quake and software Quake2), so disable the sky masking
9320 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9321 // and skymasking also looks very bad when noclipping outside the
9322 // level, so don't use it then either.
9323 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9325 R_Mesh_ResetTextureState();
9326 if (skyrendermasked)
9328 R_SetupShader_DepthOrShadow();
9329 // depth-only (masking)
9330 GL_ColorMask(0,0,0,0);
9331 // just to make sure that braindead drivers don't draw
9332 // anything despite that colormask...
9333 GL_BlendFunc(GL_ZERO, GL_ONE);
9334 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9335 if (rsurface.batchvertex3fbuffer)
9336 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9338 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9342 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9344 GL_BlendFunc(GL_ONE, GL_ZERO);
9345 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9346 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9347 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9350 if (skyrendermasked)
9351 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9353 R_Mesh_ResetTextureState();
9354 GL_Color(1, 1, 1, 1);
9357 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9358 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9359 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9361 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9365 // render screenspace normalmap to texture
9367 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9372 // bind lightmap texture
9374 // water/refraction/reflection/camera surfaces have to be handled specially
9375 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9377 int start, end, startplaneindex;
9378 for (start = 0;start < texturenumsurfaces;start = end)
9380 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9381 if(startplaneindex < 0)
9383 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9384 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9388 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9390 // now that we have a batch using the same planeindex, render it
9391 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9393 // render water or distortion background
9395 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));
9397 // blend surface on top
9398 GL_DepthMask(false);
9399 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9402 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9404 // render surface with reflection texture as input
9405 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9406 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));
9413 // render surface batch normally
9414 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9415 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9419 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9421 // OpenGL 1.3 path - anything not completely ancient
9422 qboolean applycolor;
9425 const texturelayer_t *layer;
9426 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);
9427 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9429 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9432 int layertexrgbscale;
9433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9435 if (layerindex == 0)
9439 GL_AlphaTest(false);
9440 GL_DepthFunc(GL_EQUAL);
9443 GL_DepthMask(layer->depthmask && writedepth);
9444 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9445 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9447 layertexrgbscale = 4;
9448 VectorScale(layer->color, 0.25f, layercolor);
9450 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9452 layertexrgbscale = 2;
9453 VectorScale(layer->color, 0.5f, layercolor);
9457 layertexrgbscale = 1;
9458 VectorScale(layer->color, 1.0f, layercolor);
9460 layercolor[3] = layer->color[3];
9461 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9462 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9463 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9464 switch (layer->type)
9466 case TEXTURELAYERTYPE_LITTEXTURE:
9467 // single-pass lightmapped texture with 2x rgbscale
9468 R_Mesh_TexBind(0, r_texture_white);
9469 R_Mesh_TexMatrix(0, NULL);
9470 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9471 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9472 R_Mesh_TexBind(1, layer->texture);
9473 R_Mesh_TexMatrix(1, &layer->texmatrix);
9474 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9475 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9476 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9477 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9478 else if (FAKELIGHT_ENABLED)
9479 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9480 else if (rsurface.uselightmaptexture)
9481 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9483 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9485 case TEXTURELAYERTYPE_TEXTURE:
9486 // singletexture unlit texture with transparency support
9487 R_Mesh_TexBind(0, layer->texture);
9488 R_Mesh_TexMatrix(0, &layer->texmatrix);
9489 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9490 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9491 R_Mesh_TexBind(1, 0);
9492 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9493 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9495 case TEXTURELAYERTYPE_FOG:
9496 // singletexture fogging
9499 R_Mesh_TexBind(0, layer->texture);
9500 R_Mesh_TexMatrix(0, &layer->texmatrix);
9501 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9502 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9506 R_Mesh_TexBind(0, 0);
9507 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9509 R_Mesh_TexBind(1, 0);
9510 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9511 // generate a color array for the fog pass
9512 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9513 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9517 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9520 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9522 GL_DepthFunc(GL_LEQUAL);
9523 GL_AlphaTest(false);
9527 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9529 // OpenGL 1.1 - crusty old voodoo path
9532 const texturelayer_t *layer;
9533 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);
9534 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9536 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9538 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9540 if (layerindex == 0)
9544 GL_AlphaTest(false);
9545 GL_DepthFunc(GL_EQUAL);
9548 GL_DepthMask(layer->depthmask && writedepth);
9549 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9550 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9551 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9552 switch (layer->type)
9554 case TEXTURELAYERTYPE_LITTEXTURE:
9555 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9557 // two-pass lit texture with 2x rgbscale
9558 // first the lightmap pass
9559 R_Mesh_TexBind(0, r_texture_white);
9560 R_Mesh_TexMatrix(0, NULL);
9561 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9562 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9563 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9564 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9565 else if (FAKELIGHT_ENABLED)
9566 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9567 else if (rsurface.uselightmaptexture)
9568 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9570 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9571 // then apply the texture to it
9572 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9573 R_Mesh_TexBind(0, layer->texture);
9574 R_Mesh_TexMatrix(0, &layer->texmatrix);
9575 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9576 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9577 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);
9581 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9582 R_Mesh_TexBind(0, layer->texture);
9583 R_Mesh_TexMatrix(0, &layer->texmatrix);
9584 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9585 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9586 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9587 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);
9589 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);
9592 case TEXTURELAYERTYPE_TEXTURE:
9593 // singletexture unlit texture with transparency support
9594 R_Mesh_TexBind(0, layer->texture);
9595 R_Mesh_TexMatrix(0, &layer->texmatrix);
9596 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9597 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9598 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);
9600 case TEXTURELAYERTYPE_FOG:
9601 // singletexture fogging
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);
9611 R_Mesh_TexBind(0, 0);
9612 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9614 // generate a color array for the fog pass
9615 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9616 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9620 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9625 GL_DepthFunc(GL_LEQUAL);
9626 GL_AlphaTest(false);
9630 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9634 r_vertexgeneric_t *batchvertex;
9637 // R_Mesh_ResetTextureState();
9638 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9640 if(rsurface.texture && rsurface.texture->currentskinframe)
9642 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9643 c[3] *= rsurface.texture->currentalpha;
9653 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9655 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9656 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9657 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9660 // brighten it up (as texture value 127 means "unlit")
9661 c[0] *= 2 * r_refdef.view.colorscale;
9662 c[1] *= 2 * r_refdef.view.colorscale;
9663 c[2] *= 2 * r_refdef.view.colorscale;
9665 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9666 c[3] *= r_wateralpha.value;
9668 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9670 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9671 GL_DepthMask(false);
9673 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9675 GL_BlendFunc(GL_ONE, GL_ONE);
9676 GL_DepthMask(false);
9678 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9680 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9681 GL_DepthMask(false);
9683 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9685 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9686 GL_DepthMask(false);
9690 GL_BlendFunc(GL_ONE, GL_ZERO);
9691 GL_DepthMask(writedepth);
9694 if (r_showsurfaces.integer == 3)
9696 rsurface.passcolor4f = NULL;
9698 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9700 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9702 rsurface.passcolor4f = NULL;
9703 rsurface.passcolor4f_vertexbuffer = 0;
9704 rsurface.passcolor4f_bufferoffset = 0;
9706 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9708 qboolean applycolor = true;
9711 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9713 r_refdef.lightmapintensity = 1;
9714 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9715 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9717 else if (FAKELIGHT_ENABLED)
9719 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9721 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9722 RSurf_DrawBatch_GL11_ApplyFakeLight();
9723 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9727 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9729 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9730 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9731 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9734 if(!rsurface.passcolor4f)
9735 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9737 RSurf_DrawBatch_GL11_ApplyAmbient();
9738 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9739 if(r_refdef.fogenabled)
9740 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9741 RSurf_DrawBatch_GL11_ClampColor();
9743 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9744 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9747 else if (!r_refdef.view.showdebug)
9749 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9750 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9751 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9753 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9754 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9756 R_Mesh_PrepareVertices_Generic_Unlock();
9759 else if (r_showsurfaces.integer == 4)
9761 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9762 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9763 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9765 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9766 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9767 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9769 R_Mesh_PrepareVertices_Generic_Unlock();
9772 else if (r_showsurfaces.integer == 2)
9775 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9776 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9777 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9779 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9780 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9781 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9782 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9783 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9784 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9785 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9787 R_Mesh_PrepareVertices_Generic_Unlock();
9788 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9792 int texturesurfaceindex;
9794 const msurface_t *surface;
9795 float surfacecolor4f[4];
9796 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9797 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9799 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9801 surface = texturesurfacelist[texturesurfaceindex];
9802 k = (int)(((size_t)surface) / sizeof(msurface_t));
9803 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9804 for (j = 0;j < surface->num_vertices;j++)
9806 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9807 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9811 R_Mesh_PrepareVertices_Generic_Unlock();
9816 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9819 RSurf_SetupDepthAndCulling();
9820 if (r_showsurfaces.integer)
9822 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9825 switch (vid.renderpath)
9827 case RENDERPATH_GL20:
9828 case RENDERPATH_D3D9:
9829 case RENDERPATH_D3D10:
9830 case RENDERPATH_D3D11:
9831 case RENDERPATH_SOFT:
9832 case RENDERPATH_GLES2:
9833 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9835 case RENDERPATH_GL13:
9836 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9838 case RENDERPATH_GL11:
9839 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9845 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9848 RSurf_SetupDepthAndCulling();
9849 if (r_showsurfaces.integer)
9851 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9854 switch (vid.renderpath)
9856 case RENDERPATH_GL20:
9857 case RENDERPATH_D3D9:
9858 case RENDERPATH_D3D10:
9859 case RENDERPATH_D3D11:
9860 case RENDERPATH_SOFT:
9861 case RENDERPATH_GLES2:
9862 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9864 case RENDERPATH_GL13:
9865 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9867 case RENDERPATH_GL11:
9868 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9874 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9877 int texturenumsurfaces, endsurface;
9879 const msurface_t *surface;
9880 #define MAXBATCH_TRANSPARENTSURFACES 256
9881 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9883 // if the model is static it doesn't matter what value we give for
9884 // wantnormals and wanttangents, so this logic uses only rules applicable
9885 // to a model, knowing that they are meaningless otherwise
9886 if (ent == r_refdef.scene.worldentity)
9887 RSurf_ActiveWorldEntity();
9888 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9889 RSurf_ActiveModelEntity(ent, false, false, false);
9892 switch (vid.renderpath)
9894 case RENDERPATH_GL20:
9895 case RENDERPATH_D3D9:
9896 case RENDERPATH_D3D10:
9897 case RENDERPATH_D3D11:
9898 case RENDERPATH_SOFT:
9899 case RENDERPATH_GLES2:
9900 RSurf_ActiveModelEntity(ent, true, true, false);
9902 case RENDERPATH_GL13:
9903 case RENDERPATH_GL11:
9904 RSurf_ActiveModelEntity(ent, true, false, false);
9909 if (r_transparentdepthmasking.integer)
9911 qboolean setup = false;
9912 for (i = 0;i < numsurfaces;i = j)
9915 surface = rsurface.modelsurfaces + surfacelist[i];
9916 texture = surface->texture;
9917 rsurface.texture = R_GetCurrentTexture(texture);
9918 rsurface.lightmaptexture = NULL;
9919 rsurface.deluxemaptexture = NULL;
9920 rsurface.uselightmaptexture = false;
9921 // scan ahead until we find a different texture
9922 endsurface = min(i + 1024, numsurfaces);
9923 texturenumsurfaces = 0;
9924 texturesurfacelist[texturenumsurfaces++] = surface;
9925 for (;j < endsurface;j++)
9927 surface = rsurface.modelsurfaces + surfacelist[j];
9928 if (texture != surface->texture)
9930 texturesurfacelist[texturenumsurfaces++] = surface;
9932 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9934 // render the range of surfaces as depth
9938 GL_ColorMask(0,0,0,0);
9941 GL_BlendFunc(GL_ONE, GL_ZERO);
9943 // R_Mesh_ResetTextureState();
9944 R_SetupShader_DepthOrShadow();
9946 RSurf_SetupDepthAndCulling();
9947 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9948 if (rsurface.batchvertex3fbuffer)
9949 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9951 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9955 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9958 for (i = 0;i < numsurfaces;i = j)
9961 surface = rsurface.modelsurfaces + surfacelist[i];
9962 texture = surface->texture;
9963 rsurface.texture = R_GetCurrentTexture(texture);
9964 // scan ahead until we find a different texture
9965 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9966 texturenumsurfaces = 0;
9967 texturesurfacelist[texturenumsurfaces++] = surface;
9968 if(FAKELIGHT_ENABLED)
9970 rsurface.lightmaptexture = NULL;
9971 rsurface.deluxemaptexture = NULL;
9972 rsurface.uselightmaptexture = false;
9973 for (;j < endsurface;j++)
9975 surface = rsurface.modelsurfaces + surfacelist[j];
9976 if (texture != surface->texture)
9978 texturesurfacelist[texturenumsurfaces++] = surface;
9983 rsurface.lightmaptexture = surface->lightmaptexture;
9984 rsurface.deluxemaptexture = surface->deluxemaptexture;
9985 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9986 for (;j < endsurface;j++)
9988 surface = rsurface.modelsurfaces + surfacelist[j];
9989 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9991 texturesurfacelist[texturenumsurfaces++] = surface;
9994 // render the range of surfaces
9995 if (ent == r_refdef.scene.worldentity)
9996 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9998 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10000 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10003 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10005 // transparent surfaces get pushed off into the transparent queue
10006 int surfacelistindex;
10007 const msurface_t *surface;
10008 vec3_t tempcenter, center;
10009 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10011 surface = texturesurfacelist[surfacelistindex];
10012 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10013 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10014 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10015 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10016 if (queueentity->transparent_offset) // transparent offset
10018 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10019 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10020 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10022 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10026 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10028 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10030 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10032 RSurf_SetupDepthAndCulling();
10033 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10034 if (rsurface.batchvertex3fbuffer)
10035 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10037 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10041 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10043 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10046 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10049 if (!rsurface.texture->currentnumlayers)
10051 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10052 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10054 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10056 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10057 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10058 else if (!rsurface.texture->currentnumlayers)
10060 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10062 // in the deferred case, transparent surfaces were queued during prepass
10063 if (!r_shadow_usingdeferredprepass)
10064 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10068 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10069 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10074 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10077 texture_t *texture;
10078 R_FrameData_SetMark();
10079 // break the surface list down into batches by texture and use of lightmapping
10080 for (i = 0;i < numsurfaces;i = j)
10083 // texture is the base texture pointer, rsurface.texture is the
10084 // current frame/skin the texture is directing us to use (for example
10085 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10086 // use skin 1 instead)
10087 texture = surfacelist[i]->texture;
10088 rsurface.texture = R_GetCurrentTexture(texture);
10089 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10091 // if this texture is not the kind we want, skip ahead to the next one
10092 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10096 if(FAKELIGHT_ENABLED || depthonly || prepass)
10098 rsurface.lightmaptexture = NULL;
10099 rsurface.deluxemaptexture = NULL;
10100 rsurface.uselightmaptexture = false;
10101 // simply scan ahead until we find a different texture or lightmap state
10102 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10107 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10108 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10109 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10110 // simply scan ahead until we find a different texture or lightmap state
10111 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10114 // render the range of surfaces
10115 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10117 R_FrameData_ReturnToMark();
10120 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10124 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10127 if (!rsurface.texture->currentnumlayers)
10129 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10130 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10132 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10134 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10135 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10136 else if (!rsurface.texture->currentnumlayers)
10138 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10140 // in the deferred case, transparent surfaces were queued during prepass
10141 if (!r_shadow_usingdeferredprepass)
10142 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10146 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10147 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10152 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10155 texture_t *texture;
10156 R_FrameData_SetMark();
10157 // break the surface list down into batches by texture and use of lightmapping
10158 for (i = 0;i < numsurfaces;i = j)
10161 // texture is the base texture pointer, rsurface.texture is the
10162 // current frame/skin the texture is directing us to use (for example
10163 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10164 // use skin 1 instead)
10165 texture = surfacelist[i]->texture;
10166 rsurface.texture = R_GetCurrentTexture(texture);
10167 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10169 // if this texture is not the kind we want, skip ahead to the next one
10170 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10174 if(FAKELIGHT_ENABLED || depthonly || prepass)
10176 rsurface.lightmaptexture = NULL;
10177 rsurface.deluxemaptexture = NULL;
10178 rsurface.uselightmaptexture = false;
10179 // simply scan ahead until we find a different texture or lightmap state
10180 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10185 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10186 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10187 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10188 // simply scan ahead until we find a different texture or lightmap state
10189 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10192 // render the range of surfaces
10193 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10195 R_FrameData_ReturnToMark();
10198 float locboxvertex3f[6*4*3] =
10200 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10201 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10202 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10203 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10204 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10205 1,0,0, 0,0,0, 0,1,0, 1,1,0
10208 unsigned short locboxelements[6*2*3] =
10213 12,13,14, 12,14,15,
10214 16,17,18, 16,18,19,
10218 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10221 cl_locnode_t *loc = (cl_locnode_t *)ent;
10223 float vertex3f[6*4*3];
10225 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10226 GL_DepthMask(false);
10227 GL_DepthRange(0, 1);
10228 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10229 GL_DepthTest(true);
10230 GL_CullFace(GL_NONE);
10231 R_EntityMatrix(&identitymatrix);
10233 // R_Mesh_ResetTextureState();
10235 i = surfacelist[0];
10236 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10237 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10238 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10239 surfacelist[0] < 0 ? 0.5f : 0.125f);
10241 if (VectorCompare(loc->mins, loc->maxs))
10243 VectorSet(size, 2, 2, 2);
10244 VectorMA(loc->mins, -0.5f, size, mins);
10248 VectorCopy(loc->mins, mins);
10249 VectorSubtract(loc->maxs, loc->mins, size);
10252 for (i = 0;i < 6*4*3;)
10253 for (j = 0;j < 3;j++, i++)
10254 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10256 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10257 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10258 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10261 void R_DrawLocs(void)
10264 cl_locnode_t *loc, *nearestloc;
10266 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10267 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10269 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10270 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10274 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10276 if (decalsystem->decals)
10277 Mem_Free(decalsystem->decals);
10278 memset(decalsystem, 0, sizeof(*decalsystem));
10281 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)
10284 tridecal_t *decals;
10287 // expand or initialize the system
10288 if (decalsystem->maxdecals <= decalsystem->numdecals)
10290 decalsystem_t old = *decalsystem;
10291 qboolean useshortelements;
10292 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10293 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10294 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)));
10295 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10296 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10297 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10298 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10299 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10300 if (decalsystem->numdecals)
10301 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10303 Mem_Free(old.decals);
10304 for (i = 0;i < decalsystem->maxdecals*3;i++)
10305 decalsystem->element3i[i] = i;
10306 if (useshortelements)
10307 for (i = 0;i < decalsystem->maxdecals*3;i++)
10308 decalsystem->element3s[i] = i;
10311 // grab a decal and search for another free slot for the next one
10312 decals = decalsystem->decals;
10313 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10314 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10316 decalsystem->freedecal = i;
10317 if (decalsystem->numdecals <= i)
10318 decalsystem->numdecals = i + 1;
10320 // initialize the decal
10322 decal->triangleindex = triangleindex;
10323 decal->surfaceindex = surfaceindex;
10324 decal->decalsequence = decalsequence;
10325 decal->color4f[0][0] = c0[0];
10326 decal->color4f[0][1] = c0[1];
10327 decal->color4f[0][2] = c0[2];
10328 decal->color4f[0][3] = 1;
10329 decal->color4f[1][0] = c1[0];
10330 decal->color4f[1][1] = c1[1];
10331 decal->color4f[1][2] = c1[2];
10332 decal->color4f[1][3] = 1;
10333 decal->color4f[2][0] = c2[0];
10334 decal->color4f[2][1] = c2[1];
10335 decal->color4f[2][2] = c2[2];
10336 decal->color4f[2][3] = 1;
10337 decal->vertex3f[0][0] = v0[0];
10338 decal->vertex3f[0][1] = v0[1];
10339 decal->vertex3f[0][2] = v0[2];
10340 decal->vertex3f[1][0] = v1[0];
10341 decal->vertex3f[1][1] = v1[1];
10342 decal->vertex3f[1][2] = v1[2];
10343 decal->vertex3f[2][0] = v2[0];
10344 decal->vertex3f[2][1] = v2[1];
10345 decal->vertex3f[2][2] = v2[2];
10346 decal->texcoord2f[0][0] = t0[0];
10347 decal->texcoord2f[0][1] = t0[1];
10348 decal->texcoord2f[1][0] = t1[0];
10349 decal->texcoord2f[1][1] = t1[1];
10350 decal->texcoord2f[2][0] = t2[0];
10351 decal->texcoord2f[2][1] = t2[1];
10354 extern cvar_t cl_decals_bias;
10355 extern cvar_t cl_decals_models;
10356 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10357 // baseparms, parms, temps
10358 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)
10363 const float *vertex3f;
10364 const float *normal3f;
10366 float points[2][9][3];
10373 e = rsurface.modelelement3i + 3*triangleindex;
10375 vertex3f = rsurface.modelvertex3f;
10376 normal3f = rsurface.modelnormal3f;
10380 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10382 index = 3*e[cornerindex];
10383 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10388 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10390 index = 3*e[cornerindex];
10391 VectorCopy(vertex3f + index, v[cornerindex]);
10396 //TriangleNormal(v[0], v[1], v[2], normal);
10397 //if (DotProduct(normal, localnormal) < 0.0f)
10399 // clip by each of the box planes formed from the projection matrix
10400 // if anything survives, we emit the decal
10401 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]);
10404 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]);
10407 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]);
10410 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]);
10413 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]);
10416 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]);
10419 // some part of the triangle survived, so we have to accept it...
10422 // dynamic always uses the original triangle
10424 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10426 index = 3*e[cornerindex];
10427 VectorCopy(vertex3f + index, v[cornerindex]);
10430 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10432 // convert vertex positions to texcoords
10433 Matrix4x4_Transform(projection, v[cornerindex], temp);
10434 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10435 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10436 // calculate distance fade from the projection origin
10437 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10438 f = bound(0.0f, f, 1.0f);
10439 c[cornerindex][0] = r * f;
10440 c[cornerindex][1] = g * f;
10441 c[cornerindex][2] = b * f;
10442 c[cornerindex][3] = 1.0f;
10443 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10446 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);
10448 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10449 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);
10451 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)
10453 matrix4x4_t projection;
10454 decalsystem_t *decalsystem;
10457 const msurface_t *surface;
10458 const msurface_t *surfaces;
10459 const int *surfacelist;
10460 const texture_t *texture;
10462 int numsurfacelist;
10463 int surfacelistindex;
10466 float localorigin[3];
10467 float localnormal[3];
10468 float localmins[3];
10469 float localmaxs[3];
10472 float planes[6][4];
10475 int bih_triangles_count;
10476 int bih_triangles[256];
10477 int bih_surfaces[256];
10479 decalsystem = &ent->decalsystem;
10480 model = ent->model;
10481 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10483 R_DecalSystem_Reset(&ent->decalsystem);
10487 if (!model->brush.data_leafs && !cl_decals_models.integer)
10489 if (decalsystem->model)
10490 R_DecalSystem_Reset(decalsystem);
10494 if (decalsystem->model != model)
10495 R_DecalSystem_Reset(decalsystem);
10496 decalsystem->model = model;
10498 RSurf_ActiveModelEntity(ent, true, false, false);
10500 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10501 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10502 VectorNormalize(localnormal);
10503 localsize = worldsize*rsurface.inversematrixscale;
10504 localmins[0] = localorigin[0] - localsize;
10505 localmins[1] = localorigin[1] - localsize;
10506 localmins[2] = localorigin[2] - localsize;
10507 localmaxs[0] = localorigin[0] + localsize;
10508 localmaxs[1] = localorigin[1] + localsize;
10509 localmaxs[2] = localorigin[2] + localsize;
10511 //VectorCopy(localnormal, planes[4]);
10512 //VectorVectors(planes[4], planes[2], planes[0]);
10513 AnglesFromVectors(angles, localnormal, NULL, false);
10514 AngleVectors(angles, planes[0], planes[2], planes[4]);
10515 VectorNegate(planes[0], planes[1]);
10516 VectorNegate(planes[2], planes[3]);
10517 VectorNegate(planes[4], planes[5]);
10518 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10519 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10520 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10521 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10522 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10523 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10528 matrix4x4_t forwardprojection;
10529 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10530 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10535 float projectionvector[4][3];
10536 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10537 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10538 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10539 projectionvector[0][0] = planes[0][0] * ilocalsize;
10540 projectionvector[0][1] = planes[1][0] * ilocalsize;
10541 projectionvector[0][2] = planes[2][0] * ilocalsize;
10542 projectionvector[1][0] = planes[0][1] * ilocalsize;
10543 projectionvector[1][1] = planes[1][1] * ilocalsize;
10544 projectionvector[1][2] = planes[2][1] * ilocalsize;
10545 projectionvector[2][0] = planes[0][2] * ilocalsize;
10546 projectionvector[2][1] = planes[1][2] * ilocalsize;
10547 projectionvector[2][2] = planes[2][2] * ilocalsize;
10548 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10549 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10550 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10551 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10555 dynamic = model->surfmesh.isanimated;
10556 numsurfacelist = model->nummodelsurfaces;
10557 surfacelist = model->sortedmodelsurfaces;
10558 surfaces = model->data_surfaces;
10561 bih_triangles_count = -1;
10564 if(model->render_bih.numleafs)
10565 bih = &model->render_bih;
10566 else if(model->collision_bih.numleafs)
10567 bih = &model->collision_bih;
10570 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10571 if(bih_triangles_count == 0)
10573 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10575 if(bih_triangles_count > 0)
10577 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10579 surfaceindex = bih_surfaces[triangleindex];
10580 surface = surfaces + surfaceindex;
10581 texture = surface->texture;
10582 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10584 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10586 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10591 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10593 surfaceindex = surfacelist[surfacelistindex];
10594 surface = surfaces + surfaceindex;
10595 // check cull box first because it rejects more than any other check
10596 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10598 // skip transparent surfaces
10599 texture = surface->texture;
10600 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10602 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10604 numtriangles = surface->num_triangles;
10605 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10606 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10611 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10612 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)
10614 int renderentityindex;
10615 float worldmins[3];
10616 float worldmaxs[3];
10617 entity_render_t *ent;
10619 if (!cl_decals_newsystem.integer)
10622 worldmins[0] = worldorigin[0] - worldsize;
10623 worldmins[1] = worldorigin[1] - worldsize;
10624 worldmins[2] = worldorigin[2] - worldsize;
10625 worldmaxs[0] = worldorigin[0] + worldsize;
10626 worldmaxs[1] = worldorigin[1] + worldsize;
10627 worldmaxs[2] = worldorigin[2] + worldsize;
10629 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10631 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10633 ent = r_refdef.scene.entities[renderentityindex];
10634 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10637 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10641 typedef struct r_decalsystem_splatqueue_s
10643 vec3_t worldorigin;
10644 vec3_t worldnormal;
10650 r_decalsystem_splatqueue_t;
10652 int r_decalsystem_numqueued = 0;
10653 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10655 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)
10657 r_decalsystem_splatqueue_t *queue;
10659 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10662 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10663 VectorCopy(worldorigin, queue->worldorigin);
10664 VectorCopy(worldnormal, queue->worldnormal);
10665 Vector4Set(queue->color, r, g, b, a);
10666 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10667 queue->worldsize = worldsize;
10668 queue->decalsequence = cl.decalsequence++;
10671 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10674 r_decalsystem_splatqueue_t *queue;
10676 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10677 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);
10678 r_decalsystem_numqueued = 0;
10681 extern cvar_t cl_decals_max;
10682 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10685 decalsystem_t *decalsystem = &ent->decalsystem;
10692 if (!decalsystem->numdecals)
10695 if (r_showsurfaces.integer)
10698 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10700 R_DecalSystem_Reset(decalsystem);
10704 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10705 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10707 if (decalsystem->lastupdatetime)
10708 frametime = (cl.time - decalsystem->lastupdatetime);
10711 decalsystem->lastupdatetime = cl.time;
10712 decal = decalsystem->decals;
10713 numdecals = decalsystem->numdecals;
10715 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10717 if (decal->color4f[0][3])
10719 decal->lived += frametime;
10720 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10722 memset(decal, 0, sizeof(*decal));
10723 if (decalsystem->freedecal > i)
10724 decalsystem->freedecal = i;
10728 decal = decalsystem->decals;
10729 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10732 // collapse the array by shuffling the tail decals into the gaps
10735 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10736 decalsystem->freedecal++;
10737 if (decalsystem->freedecal == numdecals)
10739 decal[decalsystem->freedecal] = decal[--numdecals];
10742 decalsystem->numdecals = numdecals;
10744 if (numdecals <= 0)
10746 // if there are no decals left, reset decalsystem
10747 R_DecalSystem_Reset(decalsystem);
10751 extern skinframe_t *decalskinframe;
10752 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10755 decalsystem_t *decalsystem = &ent->decalsystem;
10764 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10767 numdecals = decalsystem->numdecals;
10771 if (r_showsurfaces.integer)
10774 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10776 R_DecalSystem_Reset(decalsystem);
10780 // if the model is static it doesn't matter what value we give for
10781 // wantnormals and wanttangents, so this logic uses only rules applicable
10782 // to a model, knowing that they are meaningless otherwise
10783 if (ent == r_refdef.scene.worldentity)
10784 RSurf_ActiveWorldEntity();
10786 RSurf_ActiveModelEntity(ent, false, false, false);
10788 decalsystem->lastupdatetime = cl.time;
10789 decal = decalsystem->decals;
10791 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10793 // update vertex positions for animated models
10794 v3f = decalsystem->vertex3f;
10795 c4f = decalsystem->color4f;
10796 t2f = decalsystem->texcoord2f;
10797 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10799 if (!decal->color4f[0][3])
10802 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10805 // update color values for fading decals
10806 if (decal->lived >= cl_decals_time.value)
10807 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10811 c4f[ 0] = decal->color4f[0][0] * alpha;
10812 c4f[ 1] = decal->color4f[0][1] * alpha;
10813 c4f[ 2] = decal->color4f[0][2] * alpha;
10815 c4f[ 4] = decal->color4f[1][0] * alpha;
10816 c4f[ 5] = decal->color4f[1][1] * alpha;
10817 c4f[ 6] = decal->color4f[1][2] * alpha;
10819 c4f[ 8] = decal->color4f[2][0] * alpha;
10820 c4f[ 9] = decal->color4f[2][1] * alpha;
10821 c4f[10] = decal->color4f[2][2] * alpha;
10824 t2f[0] = decal->texcoord2f[0][0];
10825 t2f[1] = decal->texcoord2f[0][1];
10826 t2f[2] = decal->texcoord2f[1][0];
10827 t2f[3] = decal->texcoord2f[1][1];
10828 t2f[4] = decal->texcoord2f[2][0];
10829 t2f[5] = decal->texcoord2f[2][1];
10831 // update vertex positions for animated models
10832 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10834 e = rsurface.modelelement3i + 3*decal->triangleindex;
10835 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10836 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10837 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10841 VectorCopy(decal->vertex3f[0], v3f);
10842 VectorCopy(decal->vertex3f[1], v3f + 3);
10843 VectorCopy(decal->vertex3f[2], v3f + 6);
10846 if (r_refdef.fogenabled)
10848 alpha = RSurf_FogVertex(v3f);
10849 VectorScale(c4f, alpha, c4f);
10850 alpha = RSurf_FogVertex(v3f + 3);
10851 VectorScale(c4f + 4, alpha, c4f + 4);
10852 alpha = RSurf_FogVertex(v3f + 6);
10853 VectorScale(c4f + 8, alpha, c4f + 8);
10864 r_refdef.stats.drawndecals += numtris;
10866 // now render the decals all at once
10867 // (this assumes they all use one particle font texture!)
10868 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);
10869 // R_Mesh_ResetTextureState();
10870 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10871 GL_DepthMask(false);
10872 GL_DepthRange(0, 1);
10873 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10874 GL_DepthTest(true);
10875 GL_CullFace(GL_NONE);
10876 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10877 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10878 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10882 static void R_DrawModelDecals(void)
10886 // fade faster when there are too many decals
10887 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10888 for (i = 0;i < r_refdef.scene.numentities;i++)
10889 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10891 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10892 for (i = 0;i < r_refdef.scene.numentities;i++)
10893 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10894 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10896 R_DecalSystem_ApplySplatEntitiesQueue();
10898 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10899 for (i = 0;i < r_refdef.scene.numentities;i++)
10900 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10902 r_refdef.stats.totaldecals += numdecals;
10904 if (r_showsurfaces.integer)
10907 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10909 for (i = 0;i < r_refdef.scene.numentities;i++)
10911 if (!r_refdef.viewcache.entityvisible[i])
10913 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10914 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10918 extern cvar_t mod_collision_bih;
10919 void R_DrawDebugModel(void)
10921 entity_render_t *ent = rsurface.entity;
10922 int i, j, k, l, flagsmask;
10923 const msurface_t *surface;
10924 dp_model_t *model = ent->model;
10927 switch(vid.renderpath)
10929 case RENDERPATH_GL11:
10930 case RENDERPATH_GL13:
10931 case RENDERPATH_GL20:
10933 case RENDERPATH_D3D9:
10934 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10936 case RENDERPATH_D3D10:
10937 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10939 case RENDERPATH_D3D11:
10940 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10942 case RENDERPATH_SOFT:
10943 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10945 case RENDERPATH_GLES2:
10946 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10950 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10952 // R_Mesh_ResetTextureState();
10953 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10954 GL_DepthRange(0, 1);
10955 GL_DepthTest(!r_showdisabledepthtest.integer);
10956 GL_DepthMask(false);
10957 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10959 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10963 qboolean cullbox = ent == r_refdef.scene.worldentity;
10964 const q3mbrush_t *brush;
10965 const bih_t *bih = &model->collision_bih;
10966 const bih_leaf_t *bihleaf;
10967 float vertex3f[3][3];
10968 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10970 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10972 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10974 switch (bihleaf->type)
10977 brush = model->brush.data_brushes + bihleaf->itemindex;
10978 if (brush->colbrushf && brush->colbrushf->numtriangles)
10980 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);
10981 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10982 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10985 case BIH_COLLISIONTRIANGLE:
10986 triangleindex = bihleaf->itemindex;
10987 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10988 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10989 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
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(3, vertex3f[0], NULL, NULL);
10992 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10994 case BIH_RENDERTRIANGLE:
10995 triangleindex = bihleaf->itemindex;
10996 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10997 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10998 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10999 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);
11000 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11001 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11007 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11009 if (r_showtris.integer || (r_shownormals.value != 0))
11011 if (r_showdisabledepthtest.integer)
11013 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11014 GL_DepthMask(false);
11018 GL_BlendFunc(GL_ONE, GL_ZERO);
11019 GL_DepthMask(true);
11021 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11023 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11025 rsurface.texture = R_GetCurrentTexture(surface->texture);
11026 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11028 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11029 if (r_showtris.value > 0)
11031 if (!rsurface.texture->currentlayers->depthmask)
11032 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11033 else if (ent == r_refdef.scene.worldentity)
11034 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11036 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11037 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11038 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11040 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11043 if (r_shownormals.value < 0)
11045 qglBegin(GL_LINES);
11046 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11048 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11049 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11050 qglVertex3f(v[0], v[1], v[2]);
11051 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11052 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11053 qglVertex3f(v[0], v[1], v[2]);
11058 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11060 qglBegin(GL_LINES);
11061 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11063 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11064 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11065 qglVertex3f(v[0], v[1], v[2]);
11066 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11067 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11068 qglVertex3f(v[0], v[1], v[2]);
11072 qglBegin(GL_LINES);
11073 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11075 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11076 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11077 qglVertex3f(v[0], v[1], v[2]);
11078 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11079 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11080 qglVertex3f(v[0], v[1], v[2]);
11084 qglBegin(GL_LINES);
11085 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11087 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11088 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11089 qglVertex3f(v[0], v[1], v[2]);
11090 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11091 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11092 qglVertex3f(v[0], v[1], v[2]);
11099 rsurface.texture = NULL;
11103 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11104 int r_maxsurfacelist = 0;
11105 const msurface_t **r_surfacelist = NULL;
11106 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11108 int i, j, endj, flagsmask;
11109 dp_model_t *model = r_refdef.scene.worldmodel;
11110 msurface_t *surfaces;
11111 unsigned char *update;
11112 int numsurfacelist = 0;
11116 if (r_maxsurfacelist < model->num_surfaces)
11118 r_maxsurfacelist = model->num_surfaces;
11120 Mem_Free((msurface_t**)r_surfacelist);
11121 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11124 RSurf_ActiveWorldEntity();
11126 surfaces = model->data_surfaces;
11127 update = model->brushq1.lightmapupdateflags;
11129 // update light styles on this submodel
11130 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11132 model_brush_lightstyleinfo_t *style;
11133 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11135 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11137 int *list = style->surfacelist;
11138 style->value = r_refdef.scene.lightstylevalue[style->style];
11139 for (j = 0;j < style->numsurfaces;j++)
11140 update[list[j]] = true;
11145 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11149 R_DrawDebugModel();
11150 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11154 rsurface.lightmaptexture = NULL;
11155 rsurface.deluxemaptexture = NULL;
11156 rsurface.uselightmaptexture = false;
11157 rsurface.texture = NULL;
11158 rsurface.rtlight = NULL;
11159 numsurfacelist = 0;
11160 // add visible surfaces to draw list
11161 for (i = 0;i < model->nummodelsurfaces;i++)
11163 j = model->sortedmodelsurfaces[i];
11164 if (r_refdef.viewcache.world_surfacevisible[j])
11165 r_surfacelist[numsurfacelist++] = surfaces + j;
11167 // update lightmaps if needed
11168 if (model->brushq1.firstrender)
11170 model->brushq1.firstrender = false;
11171 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11173 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11177 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11178 if (r_refdef.viewcache.world_surfacevisible[j])
11180 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11182 // don't do anything if there were no surfaces
11183 if (!numsurfacelist)
11185 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11188 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11190 // add to stats if desired
11191 if (r_speeds.integer && !skysurfaces && !depthonly)
11193 r_refdef.stats.world_surfaces += numsurfacelist;
11194 for (j = 0;j < numsurfacelist;j++)
11195 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11198 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11201 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11203 int i, j, endj, flagsmask;
11204 dp_model_t *model = ent->model;
11205 msurface_t *surfaces;
11206 unsigned char *update;
11207 int numsurfacelist = 0;
11211 if (r_maxsurfacelist < model->num_surfaces)
11213 r_maxsurfacelist = model->num_surfaces;
11215 Mem_Free((msurface_t **)r_surfacelist);
11216 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11219 // if the model is static it doesn't matter what value we give for
11220 // wantnormals and wanttangents, so this logic uses only rules applicable
11221 // to a model, knowing that they are meaningless otherwise
11222 if (ent == r_refdef.scene.worldentity)
11223 RSurf_ActiveWorldEntity();
11224 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11225 RSurf_ActiveModelEntity(ent, false, false, false);
11227 RSurf_ActiveModelEntity(ent, true, true, true);
11228 else if (depthonly)
11230 switch (vid.renderpath)
11232 case RENDERPATH_GL20:
11233 case RENDERPATH_D3D9:
11234 case RENDERPATH_D3D10:
11235 case RENDERPATH_D3D11:
11236 case RENDERPATH_SOFT:
11237 case RENDERPATH_GLES2:
11238 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11240 case RENDERPATH_GL13:
11241 case RENDERPATH_GL11:
11242 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11248 switch (vid.renderpath)
11250 case RENDERPATH_GL20:
11251 case RENDERPATH_D3D9:
11252 case RENDERPATH_D3D10:
11253 case RENDERPATH_D3D11:
11254 case RENDERPATH_SOFT:
11255 case RENDERPATH_GLES2:
11256 RSurf_ActiveModelEntity(ent, true, true, false);
11258 case RENDERPATH_GL13:
11259 case RENDERPATH_GL11:
11260 RSurf_ActiveModelEntity(ent, true, false, false);
11265 surfaces = model->data_surfaces;
11266 update = model->brushq1.lightmapupdateflags;
11268 // update light styles
11269 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11271 model_brush_lightstyleinfo_t *style;
11272 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11274 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11276 int *list = style->surfacelist;
11277 style->value = r_refdef.scene.lightstylevalue[style->style];
11278 for (j = 0;j < style->numsurfaces;j++)
11279 update[list[j]] = true;
11284 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11288 R_DrawDebugModel();
11289 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11293 rsurface.lightmaptexture = NULL;
11294 rsurface.deluxemaptexture = NULL;
11295 rsurface.uselightmaptexture = false;
11296 rsurface.texture = NULL;
11297 rsurface.rtlight = NULL;
11298 numsurfacelist = 0;
11299 // add visible surfaces to draw list
11300 for (i = 0;i < model->nummodelsurfaces;i++)
11301 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11302 // don't do anything if there were no surfaces
11303 if (!numsurfacelist)
11305 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11308 // update lightmaps if needed
11312 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11317 R_BuildLightMap(ent, surfaces + j);
11322 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11324 R_BuildLightMap(ent, surfaces + j);
11325 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11327 // add to stats if desired
11328 if (r_speeds.integer && !skysurfaces && !depthonly)
11330 r_refdef.stats.entities_surfaces += numsurfacelist;
11331 for (j = 0;j < numsurfacelist;j++)
11332 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11335 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11338 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11340 static texture_t texture;
11341 static msurface_t surface;
11342 const msurface_t *surfacelist = &surface;
11344 // fake enough texture and surface state to render this geometry
11346 texture.update_lastrenderframe = -1; // regenerate this texture
11347 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11348 texture.currentskinframe = skinframe;
11349 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11350 texture.offsetmapping = OFFSETMAPPING_OFF;
11351 texture.offsetscale = 1;
11352 texture.specularscalemod = 1;
11353 texture.specularpowermod = 1;
11355 surface.texture = &texture;
11356 surface.num_triangles = numtriangles;
11357 surface.num_firsttriangle = firsttriangle;
11358 surface.num_vertices = numvertices;
11359 surface.num_firstvertex = firstvertex;
11362 rsurface.texture = R_GetCurrentTexture(surface.texture);
11363 rsurface.lightmaptexture = NULL;
11364 rsurface.deluxemaptexture = NULL;
11365 rsurface.uselightmaptexture = false;
11366 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11369 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)
11371 static msurface_t surface;
11372 const msurface_t *surfacelist = &surface;
11374 // fake enough texture and surface state to render this geometry
11375 surface.texture = texture;
11376 surface.num_triangles = numtriangles;
11377 surface.num_firsttriangle = firsttriangle;
11378 surface.num_vertices = numvertices;
11379 surface.num_firstvertex = firstvertex;
11382 rsurface.texture = R_GetCurrentTexture(surface.texture);
11383 rsurface.lightmaptexture = NULL;
11384 rsurface.deluxemaptexture = NULL;
11385 rsurface.uselightmaptexture = false;
11386 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);