2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
147 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
148 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
149 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
150 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
151 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
152 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
153 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
154 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
156 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
157 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
158 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
159 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
160 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
161 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
163 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
164 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
165 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
166 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
167 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
168 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
170 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
171 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
172 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
173 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
175 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
176 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
177 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
178 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
179 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
180 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
181 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
183 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
184 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
185 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
186 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
187 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
188 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
189 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
190 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
191 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
192 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
194 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
196 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
198 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
200 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
201 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
202 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
203 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
204 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
205 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
206 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
207 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
208 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
215 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
217 extern cvar_t v_glslgamma;
219 extern qboolean v_flipped_state;
221 static struct r_bloomstate_s
226 int bloomwidth, bloomheight;
228 textype_t texturetype;
229 int viewfbo; // used to check if r_viewfbo cvar has changed
231 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
235 int screentexturewidth, screentextureheight;
236 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
238 int bloomtexturewidth, bloomtextureheight;
239 rtexture_t *texture_bloom;
241 // arrays for rendering the screen passes
242 float screentexcoord2f[8];
243 float bloomtexcoord2f[8];
244 float offsettexcoord2f[8];
246 r_viewport_t viewport;
250 r_waterstate_t r_waterstate;
252 /// shadow volume bsp struct with automatically growing nodes buffer
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
277 int r_texture_numcubemaps;
278 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
284 typedef struct r_qwskincache_s
286 char name[MAX_QPATH];
287 skinframe_t *skinframe;
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
304 const float r_d3dscreenvertex3f[12] =
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
315 for (i = 0;i < verts;i++)
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
329 for (i = 0;i < verts;i++)
339 // FIXME: move this to client?
342 if (gamemode == GAME_NEHAHRA)
344 Cvar_Set("gl_fogenable", "0");
345 Cvar_Set("gl_fogdensity", "0.2");
346 Cvar_Set("gl_fogred", "0.3");
347 Cvar_Set("gl_foggreen", "0.3");
348 Cvar_Set("gl_fogblue", "0.3");
350 r_refdef.fog_density = 0;
351 r_refdef.fog_red = 0;
352 r_refdef.fog_green = 0;
353 r_refdef.fog_blue = 0;
354 r_refdef.fog_alpha = 1;
355 r_refdef.fog_start = 0;
356 r_refdef.fog_end = 16384;
357 r_refdef.fog_height = 1<<30;
358 r_refdef.fog_fadedepth = 128;
359 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
362 static void R_BuildBlankTextures(void)
364 unsigned char data[4];
365 data[2] = 128; // normal X
366 data[1] = 128; // normal Y
367 data[0] = 255; // normal Z
368 data[3] = 128; // height
369 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildNoTexture(void)
390 unsigned char pix[16][16][4];
391 // this makes a light grey/dark grey checkerboard texture
392 for (y = 0;y < 16;y++)
394 for (x = 0;x < 16;x++)
396 if ((y < 8) ^ (x < 8))
412 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
415 static void R_BuildWhiteCube(void)
417 unsigned char data[6*1*1*4];
418 memset(data, 255, sizeof(data));
419 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildNormalizationCube(void)
426 vec_t s, t, intensity;
429 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430 for (side = 0;side < 6;side++)
432 for (y = 0;y < NORMSIZE;y++)
434 for (x = 0;x < NORMSIZE;x++)
436 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
472 intensity = 127.0f / sqrt(DotProduct(v, v));
473 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476 data[((side*64+y)*64+x)*4+3] = 255;
480 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
484 static void R_BuildFogTexture(void)
488 unsigned char data1[FOGWIDTH][4];
489 //unsigned char data2[FOGWIDTH][4];
492 r_refdef.fogmasktable_start = r_refdef.fog_start;
493 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494 r_refdef.fogmasktable_range = r_refdef.fogrange;
495 r_refdef.fogmasktable_density = r_refdef.fog_density;
497 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
500 d = (x * r - r_refdef.fogmasktable_start);
501 if(developer_extra.integer)
502 Con_DPrintf("%f ", d);
504 if (r_fog_exp2.integer)
505 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
507 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508 if(developer_extra.integer)
509 Con_DPrintf(" : %f ", alpha);
510 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511 if(developer_extra.integer)
512 Con_DPrintf(" = %f\n", alpha);
513 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
516 for (x = 0;x < FOGWIDTH;x++)
518 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
523 //data2[x][0] = 255 - b;
524 //data2[x][1] = 255 - b;
525 //data2[x][2] = 255 - b;
528 if (r_texture_fogattenuation)
530 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
535 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
540 static void R_BuildFogHeightTexture(void)
542 unsigned char *inpixels;
550 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551 if (r_refdef.fogheighttexturename[0])
552 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
555 r_refdef.fog_height_tablesize = 0;
556 if (r_texture_fogheighttexture)
557 R_FreeTexture(r_texture_fogheighttexture);
558 r_texture_fogheighttexture = NULL;
559 if (r_refdef.fog_height_table2d)
560 Mem_Free(r_refdef.fog_height_table2d);
561 r_refdef.fog_height_table2d = NULL;
562 if (r_refdef.fog_height_table1d)
563 Mem_Free(r_refdef.fog_height_table1d);
564 r_refdef.fog_height_table1d = NULL;
568 r_refdef.fog_height_tablesize = size;
569 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
573 // LordHavoc: now the magic - what is that table2d for? it is a cooked
574 // average fog color table accounting for every fog layer between a point
575 // and the camera. (Note: attenuation is handled separately!)
576 for (y = 0;y < size;y++)
578 for (x = 0;x < size;x++)
584 for (j = x;j <= y;j++)
586 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592 for (j = x;j >= y;j--)
594 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
605 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
608 //=======================================================================================================================================================
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
621 //=======================================================================================================================================================
623 typedef struct shaderpermutationinfo_s
628 shaderpermutationinfo_t;
630 typedef struct shadermodeinfo_s
632 const char *vertexfilename;
633 const char *geometryfilename;
634 const char *fragmentfilename;
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
643 {"#define USEDIFFUSE\n", " diffuse"},
644 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645 {"#define USEVIEWTINT\n", " viewtint"},
646 {"#define USECOLORMAPPING\n", " colormapping"},
647 {"#define USESATURATION\n", " saturation"},
648 {"#define USEFOGINSIDE\n", " foginside"},
649 {"#define USEFOGOUTSIDE\n", " fogoutside"},
650 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652 {"#define USEGAMMARAMPS\n", " gammaramps"},
653 {"#define USECUBEFILTER\n", " cubefilter"},
654 {"#define USEGLOW\n", " glow"},
655 {"#define USEBLOOM\n", " bloom"},
656 {"#define USESPECULAR\n", " specular"},
657 {"#define USEPOSTPROCESSING\n", " postprocessing"},
658 {"#define USEREFLECTION\n", " reflection"},
659 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668 {"#define USEALPHAKILL\n", " alphakill"},
669 {"#define USEREFLECTCUBE\n", " reflectcube"},
670 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671 {"#define USEBOUNCEGRID\n", " bouncegrid"},
672 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
675 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
676 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
680 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
696 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
720 struct r_glsl_permutation_s *hashnext;
722 unsigned int permutation;
724 /// indicates if we have tried compiling this permutation already
726 /// 0 if compilation failed
728 // texture units assigned to each detected uniform
729 int tex_Texture_First;
730 int tex_Texture_Second;
731 int tex_Texture_GammaRamps;
732 int tex_Texture_Normal;
733 int tex_Texture_Color;
734 int tex_Texture_Gloss;
735 int tex_Texture_Glow;
736 int tex_Texture_SecondaryNormal;
737 int tex_Texture_SecondaryColor;
738 int tex_Texture_SecondaryGloss;
739 int tex_Texture_SecondaryGlow;
740 int tex_Texture_Pants;
741 int tex_Texture_Shirt;
742 int tex_Texture_FogHeightTexture;
743 int tex_Texture_FogMask;
744 int tex_Texture_Lightmap;
745 int tex_Texture_Deluxemap;
746 int tex_Texture_Attenuation;
747 int tex_Texture_Cube;
748 int tex_Texture_Refraction;
749 int tex_Texture_Reflection;
750 int tex_Texture_ShadowMap2D;
751 int tex_Texture_CubeProjection;
752 int tex_Texture_ScreenDepth;
753 int tex_Texture_ScreenNormalMap;
754 int tex_Texture_ScreenDiffuse;
755 int tex_Texture_ScreenSpecular;
756 int tex_Texture_ReflectMask;
757 int tex_Texture_ReflectCube;
758 int tex_Texture_BounceGrid;
759 /// locations of detected uniforms in program object, or -1 if not found
760 int loc_Texture_First;
761 int loc_Texture_Second;
762 int loc_Texture_GammaRamps;
763 int loc_Texture_Normal;
764 int loc_Texture_Color;
765 int loc_Texture_Gloss;
766 int loc_Texture_Glow;
767 int loc_Texture_SecondaryNormal;
768 int loc_Texture_SecondaryColor;
769 int loc_Texture_SecondaryGloss;
770 int loc_Texture_SecondaryGlow;
771 int loc_Texture_Pants;
772 int loc_Texture_Shirt;
773 int loc_Texture_FogHeightTexture;
774 int loc_Texture_FogMask;
775 int loc_Texture_Lightmap;
776 int loc_Texture_Deluxemap;
777 int loc_Texture_Attenuation;
778 int loc_Texture_Cube;
779 int loc_Texture_Refraction;
780 int loc_Texture_Reflection;
781 int loc_Texture_ShadowMap2D;
782 int loc_Texture_CubeProjection;
783 int loc_Texture_ScreenDepth;
784 int loc_Texture_ScreenNormalMap;
785 int loc_Texture_ScreenDiffuse;
786 int loc_Texture_ScreenSpecular;
787 int loc_Texture_ReflectMask;
788 int loc_Texture_ReflectCube;
789 int loc_Texture_BounceGrid;
791 int loc_BloomBlur_Parameters;
793 int loc_Color_Ambient;
794 int loc_Color_Diffuse;
795 int loc_Color_Specular;
799 int loc_DeferredColor_Ambient;
800 int loc_DeferredColor_Diffuse;
801 int loc_DeferredColor_Specular;
802 int loc_DeferredMod_Diffuse;
803 int loc_DeferredMod_Specular;
804 int loc_DistortScaleRefractReflect;
807 int loc_FogHeightFade;
809 int loc_FogPlaneViewDist;
810 int loc_FogRangeRecip;
813 int loc_LightPosition;
814 int loc_OffsetMapping_ScaleSteps;
816 int loc_ReflectColor;
817 int loc_ReflectFactor;
818 int loc_ReflectOffset;
819 int loc_RefractColor;
821 int loc_ScreenCenterRefractReflect;
822 int loc_ScreenScaleRefractReflect;
823 int loc_ScreenToDepth;
824 int loc_ShadowMap_Parameters;
825 int loc_ShadowMap_TextureScale;
826 int loc_SpecularPower;
831 int loc_ViewTintColor;
833 int loc_ModelToLight;
835 int loc_BackgroundTexMatrix;
836 int loc_ModelViewProjectionMatrix;
837 int loc_ModelViewMatrix;
838 int loc_PixelToScreenTexCoord;
839 int loc_ModelToReflectCube;
840 int loc_ShadowMapMatrix;
841 int loc_BloomColorSubtract;
842 int loc_NormalmapScrollBlend;
843 int loc_BounceGridMatrix;
844 int loc_BounceGridIntensity;
846 r_glsl_permutation_t;
848 #define SHADERPERMUTATION_HASHSIZE 256
851 // non-degradable "lightweight" shader parameters to keep the permutations simpler
852 // these can NOT degrade! only use for simple stuff
855 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
856 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
857 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
858 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
859 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
860 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
861 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
863 #define SHADERSTATICPARMS_COUNT 7
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870 qboolean R_CompileShader_CheckStaticParms(void)
872 static int r_compileshader_staticparms_save[1];
873 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
874 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
877 if (r_glsl_saturation_redcompensate.integer)
878 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
879 if (r_glsl_vertextextureblend_usebothalphas.integer)
880 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
881 if (r_shadow_glossexact.integer)
882 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
883 if (r_glsl_postprocess.integer)
885 if (r_glsl_postprocess_uservec1_enable.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
887 if (r_glsl_postprocess_uservec2_enable.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
889 if (r_glsl_postprocess_uservec3_enable.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
891 if (r_glsl_postprocess_uservec4_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
897 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
898 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
899 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
901 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
902 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
904 shaderstaticparms_count = 0;
907 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
908 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
909 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
910 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
911 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
912 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
916 /// information about each possible shader permutation
917 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
918 /// currently selected permutation
919 r_glsl_permutation_t *r_glsl_permutation;
920 /// storage for permutations linked in the hash table
921 memexpandablearray_t r_glsl_permutationarray;
923 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
925 //unsigned int hashdepth = 0;
926 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
927 r_glsl_permutation_t *p;
928 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
930 if (p->mode == mode && p->permutation == permutation)
932 //if (hashdepth > 10)
933 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
938 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
940 p->permutation = permutation;
941 p->hashnext = r_glsl_permutationhash[mode][hashindex];
942 r_glsl_permutationhash[mode][hashindex] = p;
943 //if (hashdepth > 10)
944 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
948 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
951 if (!filename || !filename[0])
953 if (!strcmp(filename, "glsl/default.glsl"))
955 if (!glslshaderstring)
957 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958 if (glslshaderstring)
959 Con_DPrintf("Loading shaders from file %s...\n", filename);
961 glslshaderstring = (char *)builtinshaderstring;
963 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
964 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
967 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970 if (printfromdisknotice)
971 Con_DPrintf("from disk %s... ", filename);
977 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
981 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
982 char *vertexstring, *geometrystring, *fragmentstring;
983 char permutationname[256];
984 int vertstrings_count = 0;
985 int geomstrings_count = 0;
986 int fragstrings_count = 0;
987 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
988 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996 permutationname[0] = 0;
997 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
998 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
999 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1001 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1003 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1004 if(vid.support.gl20shaders130)
1006 vertstrings_list[vertstrings_count++] = "#version 130\n";
1007 geomstrings_list[geomstrings_count++] = "#version 130\n";
1008 fragstrings_list[fragstrings_count++] = "#version 130\n";
1009 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1010 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1011 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1014 // the first pretext is which type of shader to compile as
1015 // (later these will all be bound together as a program object)
1016 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1017 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1018 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1020 // the second pretext is the mode (for example a light source)
1021 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1022 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1023 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1024 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1026 // now add all the permutation pretexts
1027 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1029 if (permutation & (1<<i))
1031 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1032 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1033 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1034 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1038 // keep line numbers correct
1039 vertstrings_list[vertstrings_count++] = "\n";
1040 geomstrings_list[geomstrings_count++] = "\n";
1041 fragstrings_list[fragstrings_count++] = "\n";
1046 R_CompileShader_AddStaticParms(mode, permutation);
1047 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1048 vertstrings_count += shaderstaticparms_count;
1049 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050 geomstrings_count += shaderstaticparms_count;
1051 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052 fragstrings_count += shaderstaticparms_count;
1054 // now append the shader text itself
1055 vertstrings_list[vertstrings_count++] = vertexstring;
1056 geomstrings_list[geomstrings_count++] = geometrystring;
1057 fragstrings_list[fragstrings_count++] = fragmentstring;
1059 // if any sources were NULL, clear the respective list
1061 vertstrings_count = 0;
1062 if (!geometrystring)
1063 geomstrings_count = 0;
1064 if (!fragmentstring)
1065 fragstrings_count = 0;
1067 // compile the shader program
1068 if (vertstrings_count + geomstrings_count + fragstrings_count)
1069 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1073 qglUseProgram(p->program);CHECKGLERROR
1074 // look up all the uniform variable names we care about, so we don't
1075 // have to look them up every time we set them
1077 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1078 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1079 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1080 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1081 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1082 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1083 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1084 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1085 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1086 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1087 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1088 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1089 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1090 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1091 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1092 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1093 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1094 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1095 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1096 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1097 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1098 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1099 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1100 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1101 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1102 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1103 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1104 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1105 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1106 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1107 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1108 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1109 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1110 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1111 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1112 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1113 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1114 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1115 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1116 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1117 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1118 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1119 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1120 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1121 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1122 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1123 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1124 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1125 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1126 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1127 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1128 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1129 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1130 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1131 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1132 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1133 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1134 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1135 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1136 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1137 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1138 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1139 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1140 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1141 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1142 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1143 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1144 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1145 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1146 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1147 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1148 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1149 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1150 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1151 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1152 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1153 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1154 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1155 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1156 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1157 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1158 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1159 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1160 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1161 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1162 // initialize the samplers to refer to the texture units we use
1163 p->tex_Texture_First = -1;
1164 p->tex_Texture_Second = -1;
1165 p->tex_Texture_GammaRamps = -1;
1166 p->tex_Texture_Normal = -1;
1167 p->tex_Texture_Color = -1;
1168 p->tex_Texture_Gloss = -1;
1169 p->tex_Texture_Glow = -1;
1170 p->tex_Texture_SecondaryNormal = -1;
1171 p->tex_Texture_SecondaryColor = -1;
1172 p->tex_Texture_SecondaryGloss = -1;
1173 p->tex_Texture_SecondaryGlow = -1;
1174 p->tex_Texture_Pants = -1;
1175 p->tex_Texture_Shirt = -1;
1176 p->tex_Texture_FogHeightTexture = -1;
1177 p->tex_Texture_FogMask = -1;
1178 p->tex_Texture_Lightmap = -1;
1179 p->tex_Texture_Deluxemap = -1;
1180 p->tex_Texture_Attenuation = -1;
1181 p->tex_Texture_Cube = -1;
1182 p->tex_Texture_Refraction = -1;
1183 p->tex_Texture_Reflection = -1;
1184 p->tex_Texture_ShadowMap2D = -1;
1185 p->tex_Texture_CubeProjection = -1;
1186 p->tex_Texture_ScreenDepth = -1;
1187 p->tex_Texture_ScreenNormalMap = -1;
1188 p->tex_Texture_ScreenDiffuse = -1;
1189 p->tex_Texture_ScreenSpecular = -1;
1190 p->tex_Texture_ReflectMask = -1;
1191 p->tex_Texture_ReflectCube = -1;
1192 p->tex_Texture_BounceGrid = -1;
1194 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1195 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1196 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1197 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1198 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1199 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1200 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1201 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1202 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1203 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1204 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1205 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1206 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1207 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1208 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1209 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1210 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1211 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1212 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1213 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1214 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1215 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1216 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1217 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1218 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1219 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1220 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1221 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1222 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1223 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1225 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1228 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1232 Mem_Free(vertexstring);
1234 Mem_Free(geometrystring);
1236 Mem_Free(fragmentstring);
1239 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1241 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1242 if (r_glsl_permutation != perm)
1244 r_glsl_permutation = perm;
1245 if (!r_glsl_permutation->program)
1247 if (!r_glsl_permutation->compiled)
1248 R_GLSL_CompilePermutation(perm, mode, permutation);
1249 if (!r_glsl_permutation->program)
1251 // remove features until we find a valid permutation
1253 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1255 // reduce i more quickly whenever it would not remove any bits
1256 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1257 if (!(permutation & j))
1260 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1261 if (!r_glsl_permutation->compiled)
1262 R_GLSL_CompilePermutation(perm, mode, permutation);
1263 if (r_glsl_permutation->program)
1266 if (i >= SHADERPERMUTATION_COUNT)
1268 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1269 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270 qglUseProgram(0);CHECKGLERROR
1271 return; // no bit left to clear, entire mode is broken
1276 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1278 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1279 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1280 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1288 extern D3DCAPS9 vid_d3d9caps;
1291 struct r_hlsl_permutation_s;
1292 typedef struct r_hlsl_permutation_s
1294 /// hash lookup data
1295 struct r_hlsl_permutation_s *hashnext;
1297 unsigned int permutation;
1299 /// indicates if we have tried compiling this permutation already
1301 /// NULL if compilation failed
1302 IDirect3DVertexShader9 *vertexshader;
1303 IDirect3DPixelShader9 *pixelshader;
1305 r_hlsl_permutation_t;
1307 typedef enum D3DVSREGISTER_e
1309 D3DVSREGISTER_TexMatrix = 0, // float4x4
1310 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1311 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1312 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1313 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1314 D3DVSREGISTER_ModelToLight = 20, // float4x4
1315 D3DVSREGISTER_EyePosition = 24,
1316 D3DVSREGISTER_FogPlane = 25,
1317 D3DVSREGISTER_LightDir = 26,
1318 D3DVSREGISTER_LightPosition = 27,
1322 typedef enum D3DPSREGISTER_e
1324 D3DPSREGISTER_Alpha = 0,
1325 D3DPSREGISTER_BloomBlur_Parameters = 1,
1326 D3DPSREGISTER_ClientTime = 2,
1327 D3DPSREGISTER_Color_Ambient = 3,
1328 D3DPSREGISTER_Color_Diffuse = 4,
1329 D3DPSREGISTER_Color_Specular = 5,
1330 D3DPSREGISTER_Color_Glow = 6,
1331 D3DPSREGISTER_Color_Pants = 7,
1332 D3DPSREGISTER_Color_Shirt = 8,
1333 D3DPSREGISTER_DeferredColor_Ambient = 9,
1334 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1335 D3DPSREGISTER_DeferredColor_Specular = 11,
1336 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1337 D3DPSREGISTER_DeferredMod_Specular = 13,
1338 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1339 D3DPSREGISTER_EyePosition = 15, // unused
1340 D3DPSREGISTER_FogColor = 16,
1341 D3DPSREGISTER_FogHeightFade = 17,
1342 D3DPSREGISTER_FogPlane = 18,
1343 D3DPSREGISTER_FogPlaneViewDist = 19,
1344 D3DPSREGISTER_FogRangeRecip = 20,
1345 D3DPSREGISTER_LightColor = 21,
1346 D3DPSREGISTER_LightDir = 22, // unused
1347 D3DPSREGISTER_LightPosition = 23,
1348 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1349 D3DPSREGISTER_PixelSize = 25,
1350 D3DPSREGISTER_ReflectColor = 26,
1351 D3DPSREGISTER_ReflectFactor = 27,
1352 D3DPSREGISTER_ReflectOffset = 28,
1353 D3DPSREGISTER_RefractColor = 29,
1354 D3DPSREGISTER_Saturation = 30,
1355 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1356 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1357 D3DPSREGISTER_ScreenToDepth = 33,
1358 D3DPSREGISTER_ShadowMap_Parameters = 34,
1359 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1360 D3DPSREGISTER_SpecularPower = 36,
1361 D3DPSREGISTER_UserVec1 = 37,
1362 D3DPSREGISTER_UserVec2 = 38,
1363 D3DPSREGISTER_UserVec3 = 39,
1364 D3DPSREGISTER_UserVec4 = 40,
1365 D3DPSREGISTER_ViewTintColor = 41,
1366 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1367 D3DPSREGISTER_BloomColorSubtract = 43,
1368 D3DPSREGISTER_ViewToLight = 44, // float4x4
1369 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1370 D3DPSREGISTER_NormalmapScrollBlend = 52,
1375 /// information about each possible shader permutation
1376 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1377 /// currently selected permutation
1378 r_hlsl_permutation_t *r_hlsl_permutation;
1379 /// storage for permutations linked in the hash table
1380 memexpandablearray_t r_hlsl_permutationarray;
1382 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1384 //unsigned int hashdepth = 0;
1385 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1386 r_hlsl_permutation_t *p;
1387 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1389 if (p->mode == mode && p->permutation == permutation)
1391 //if (hashdepth > 10)
1392 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1397 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1399 p->permutation = permutation;
1400 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1401 r_hlsl_permutationhash[mode][hashindex] = p;
1402 //if (hashdepth > 10)
1403 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1407 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1410 if (!filename || !filename[0])
1412 if (!strcmp(filename, "hlsl/default.hlsl"))
1414 if (!hlslshaderstring)
1416 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417 if (hlslshaderstring)
1418 Con_DPrintf("Loading shaders from file %s...\n", filename);
1420 hlslshaderstring = (char *)builtinhlslshaderstring;
1422 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1423 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1424 return shaderstring;
1426 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429 if (printfromdisknotice)
1430 Con_DPrintf("from disk %s... ", filename);
1431 return shaderstring;
1433 return shaderstring;
1437 //#include <d3dx9shader.h>
1438 //#include <d3dx9mesh.h>
1440 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1442 DWORD *vsbin = NULL;
1443 DWORD *psbin = NULL;
1444 fs_offset_t vsbinsize;
1445 fs_offset_t psbinsize;
1446 // IDirect3DVertexShader9 *vs = NULL;
1447 // IDirect3DPixelShader9 *ps = NULL;
1448 ID3DXBuffer *vslog = NULL;
1449 ID3DXBuffer *vsbuffer = NULL;
1450 ID3DXConstantTable *vsconstanttable = NULL;
1451 ID3DXBuffer *pslog = NULL;
1452 ID3DXBuffer *psbuffer = NULL;
1453 ID3DXConstantTable *psconstanttable = NULL;
1456 char temp[MAX_INPUTLINE];
1457 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1458 qboolean debugshader = gl_paranoid.integer != 0;
1459 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1463 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1464 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1466 if ((!vsbin && vertstring) || (!psbin && fragstring))
1468 const char* dllnames_d3dx9 [] =
1492 dllhandle_t d3dx9_dll = NULL;
1493 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1495 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496 dllfunction_t d3dx9_dllfuncs[] =
1498 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1499 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1500 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1503 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1505 DWORD shaderflags = 0;
1507 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1508 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1509 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1510 if (vertstring && vertstring[0])
1514 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1515 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1516 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1517 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1520 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1523 vsbinsize = vsbuffer->GetBufferSize();
1524 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1525 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1526 vsbuffer->Release();
1530 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1531 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1535 if (fragstring && fragstring[0])
1539 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1540 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1541 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1542 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1545 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1548 psbinsize = psbuffer->GetBufferSize();
1549 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1550 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1551 psbuffer->Release();
1555 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1556 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1560 Sys_UnloadLibrary(&d3dx9_dll);
1563 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1567 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1568 if (FAILED(vsresult))
1569 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1570 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1571 if (FAILED(psresult))
1572 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1574 // free the shader data
1575 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1576 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1579 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1582 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1583 int vertstring_length = 0;
1584 int geomstring_length = 0;
1585 int fragstring_length = 0;
1587 char *vertexstring, *geometrystring, *fragmentstring;
1588 char *vertstring, *geomstring, *fragstring;
1589 char permutationname[256];
1590 char cachename[256];
1591 int vertstrings_count = 0;
1592 int geomstrings_count = 0;
1593 int fragstrings_count = 0;
1594 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 p->vertexshader = NULL;
1602 p->pixelshader = NULL;
1604 permutationname[0] = 0;
1606 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1607 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1608 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1610 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1611 strlcat(cachename, "hlsl/", sizeof(cachename));
1613 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1614 vertstrings_count = 0;
1615 geomstrings_count = 0;
1616 fragstrings_count = 0;
1617 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1618 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1619 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1621 // the first pretext is which type of shader to compile as
1622 // (later these will all be bound together as a program object)
1623 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1624 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1625 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1627 // the second pretext is the mode (for example a light source)
1628 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1629 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1630 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1631 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1632 strlcat(cachename, modeinfo->name, sizeof(cachename));
1634 // now add all the permutation pretexts
1635 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1637 if (permutation & (1<<i))
1639 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1640 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1641 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1642 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1643 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1647 // keep line numbers correct
1648 vertstrings_list[vertstrings_count++] = "\n";
1649 geomstrings_list[geomstrings_count++] = "\n";
1650 fragstrings_list[fragstrings_count++] = "\n";
1655 R_CompileShader_AddStaticParms(mode, permutation);
1656 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657 vertstrings_count += shaderstaticparms_count;
1658 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659 geomstrings_count += shaderstaticparms_count;
1660 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661 fragstrings_count += shaderstaticparms_count;
1663 // replace spaces in the cachename with _ characters
1664 for (i = 0;cachename[i];i++)
1665 if (cachename[i] == ' ')
1668 // now append the shader text itself
1669 vertstrings_list[vertstrings_count++] = vertexstring;
1670 geomstrings_list[geomstrings_count++] = geometrystring;
1671 fragstrings_list[fragstrings_count++] = fragmentstring;
1673 // if any sources were NULL, clear the respective list
1675 vertstrings_count = 0;
1676 if (!geometrystring)
1677 geomstrings_count = 0;
1678 if (!fragmentstring)
1679 fragstrings_count = 0;
1681 vertstring_length = 0;
1682 for (i = 0;i < vertstrings_count;i++)
1683 vertstring_length += strlen(vertstrings_list[i]);
1684 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1685 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1686 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1688 geomstring_length = 0;
1689 for (i = 0;i < geomstrings_count;i++)
1690 geomstring_length += strlen(geomstrings_list[i]);
1691 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1692 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1693 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1695 fragstring_length = 0;
1696 for (i = 0;i < fragstrings_count;i++)
1697 fragstring_length += strlen(fragstrings_list[i]);
1698 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1699 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1700 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1702 // try to load the cached shader, or generate one
1703 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1705 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1706 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1708 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1712 Mem_Free(vertstring);
1714 Mem_Free(geomstring);
1716 Mem_Free(fragstring);
1718 Mem_Free(vertexstring);
1720 Mem_Free(geometrystring);
1722 Mem_Free(fragmentstring);
1725 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1726 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1727 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1728 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1729 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1730 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1732 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1739 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1741 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1742 if (r_hlsl_permutation != perm)
1744 r_hlsl_permutation = perm;
1745 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747 if (!r_hlsl_permutation->compiled)
1748 R_HLSL_CompilePermutation(perm, mode, permutation);
1749 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1751 // remove features until we find a valid permutation
1753 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1755 // reduce i more quickly whenever it would not remove any bits
1756 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1757 if (!(permutation & j))
1760 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1761 if (!r_hlsl_permutation->compiled)
1762 R_HLSL_CompilePermutation(perm, mode, permutation);
1763 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1766 if (i >= SHADERPERMUTATION_COUNT)
1768 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1769 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770 return; // no bit left to clear, entire mode is broken
1774 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1775 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1777 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1778 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1779 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1783 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1785 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1786 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1787 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1788 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1791 void R_GLSL_Restart_f(void)
1793 unsigned int i, limit;
1794 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1795 Mem_Free(glslshaderstring);
1796 glslshaderstring = NULL;
1797 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1798 Mem_Free(hlslshaderstring);
1799 hlslshaderstring = NULL;
1800 switch(vid.renderpath)
1802 case RENDERPATH_D3D9:
1805 r_hlsl_permutation_t *p;
1806 r_hlsl_permutation = NULL;
1807 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1808 for (i = 0;i < limit;i++)
1810 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1812 if (p->vertexshader)
1813 IDirect3DVertexShader9_Release(p->vertexshader);
1815 IDirect3DPixelShader9_Release(p->pixelshader);
1816 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1819 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1823 case RENDERPATH_D3D10:
1824 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826 case RENDERPATH_D3D11:
1827 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1829 case RENDERPATH_GL20:
1830 case RENDERPATH_GLES2:
1832 r_glsl_permutation_t *p;
1833 r_glsl_permutation = NULL;
1834 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1835 for (i = 0;i < limit;i++)
1837 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1839 GL_Backend_FreeProgram(p->program);
1840 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1843 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1846 case RENDERPATH_GL13:
1847 case RENDERPATH_GL11:
1849 case RENDERPATH_SOFT:
1854 void R_GLSL_DumpShader_f(void)
1859 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1862 FS_Print(file, "/* The engine may define the following macros:\n");
1863 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1864 for (i = 0;i < SHADERMODE_COUNT;i++)
1865 FS_Print(file, glslshadermodeinfo[i].pretext);
1866 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1867 FS_Print(file, shaderpermutationinfo[i].pretext);
1868 FS_Print(file, "*/\n");
1869 FS_Print(file, builtinshaderstring);
1871 Con_Printf("glsl/default.glsl written\n");
1874 Con_Printf("failed to write to glsl/default.glsl\n");
1876 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1879 FS_Print(file, "/* The engine may define the following macros:\n");
1880 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1881 for (i = 0;i < SHADERMODE_COUNT;i++)
1882 FS_Print(file, hlslshadermodeinfo[i].pretext);
1883 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884 FS_Print(file, shaderpermutationinfo[i].pretext);
1885 FS_Print(file, "*/\n");
1886 FS_Print(file, builtinhlslshaderstring);
1888 Con_Printf("hlsl/default.hlsl written\n");
1891 Con_Printf("failed to write to hlsl/default.hlsl\n");
1894 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1897 texturemode = GL_MODULATE;
1898 switch (vid.renderpath)
1900 case RENDERPATH_D3D9:
1902 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1903 R_Mesh_TexBind(GL20TU_FIRST , first );
1904 R_Mesh_TexBind(GL20TU_SECOND, second);
1907 case RENDERPATH_D3D10:
1908 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1910 case RENDERPATH_D3D11:
1911 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1913 case RENDERPATH_GL20:
1914 case RENDERPATH_GLES2:
1915 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1916 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1917 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1919 case RENDERPATH_GL13:
1920 R_Mesh_TexBind(0, first );
1921 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1922 R_Mesh_TexBind(1, second);
1924 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1926 case RENDERPATH_GL11:
1927 R_Mesh_TexBind(0, first );
1929 case RENDERPATH_SOFT:
1930 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1931 R_Mesh_TexBind(GL20TU_FIRST , first );
1932 R_Mesh_TexBind(GL20TU_SECOND, second);
1937 void R_SetupShader_DepthOrShadow(void)
1939 switch (vid.renderpath)
1941 case RENDERPATH_D3D9:
1943 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1946 case RENDERPATH_D3D10:
1947 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949 case RENDERPATH_D3D11:
1950 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952 case RENDERPATH_GL20:
1953 case RENDERPATH_GLES2:
1954 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1956 case RENDERPATH_GL13:
1957 R_Mesh_TexBind(0, 0);
1958 R_Mesh_TexBind(1, 0);
1960 case RENDERPATH_GL11:
1961 R_Mesh_TexBind(0, 0);
1963 case RENDERPATH_SOFT:
1964 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1969 void R_SetupShader_ShowDepth(void)
1971 switch (vid.renderpath)
1973 case RENDERPATH_D3D9:
1975 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1978 case RENDERPATH_D3D10:
1979 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1981 case RENDERPATH_D3D11:
1982 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1984 case RENDERPATH_GL20:
1985 case RENDERPATH_GLES2:
1986 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1988 case RENDERPATH_GL13:
1990 case RENDERPATH_GL11:
1992 case RENDERPATH_SOFT:
1993 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1998 extern qboolean r_shadow_usingdeferredprepass;
1999 extern cvar_t r_shadow_deferred_8bitrange;
2000 extern rtexture_t *r_shadow_attenuationgradienttexture;
2001 extern rtexture_t *r_shadow_attenuation2dtexture;
2002 extern rtexture_t *r_shadow_attenuation3dtexture;
2003 extern qboolean r_shadow_usingshadowmap2d;
2004 extern qboolean r_shadow_usingshadowmaportho;
2005 extern float r_shadow_shadowmap_texturescale[2];
2006 extern float r_shadow_shadowmap_parameters[4];
2007 extern qboolean r_shadow_shadowmapvsdct;
2008 extern qboolean r_shadow_shadowmapsampler;
2009 extern int r_shadow_shadowmappcf;
2010 extern rtexture_t *r_shadow_shadowmap2dtexture;
2011 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2012 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2013 extern matrix4x4_t r_shadow_shadowmapmatrix;
2014 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2015 extern int r_shadow_prepass_width;
2016 extern int r_shadow_prepass_height;
2017 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2018 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2019 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2020 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2021 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2023 #define BLENDFUNC_ALLOWS_COLORMOD 1
2024 #define BLENDFUNC_ALLOWS_FOG 2
2025 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2026 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2027 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2028 static int R_BlendFuncFlags(int src, int dst)
2032 // a blendfunc allows colormod if:
2033 // a) it can never keep the destination pixel invariant, or
2034 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2035 // this is to prevent unintended side effects from colormod
2037 // a blendfunc allows fog if:
2038 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2039 // this is to prevent unintended side effects from fog
2041 // these checks are the output of fogeval.pl
2043 r |= BLENDFUNC_ALLOWS_COLORMOD;
2044 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2045 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2046 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2047 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2048 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2052 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2053 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2054 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2055 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2057 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2059 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2064 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2071 // select a permutation of the lighting shader appropriate to this
2072 // combination of texture, entity, light source, and fogging, only use the
2073 // minimum features necessary to avoid wasting rendering time in the
2074 // fragment shader on features that are not being used
2075 unsigned int permutation = 0;
2076 unsigned int mode = 0;
2078 static float dummy_colormod[3] = {1, 1, 1};
2079 float *colormod = rsurface.colormod;
2081 matrix4x4_t tempmatrix;
2082 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2083 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2084 permutation |= SHADERPERMUTATION_ALPHAKILL;
2085 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2086 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2087 if (rsurfacepass == RSURFPASS_BACKGROUND)
2089 // distorted background
2090 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2092 mode = SHADERMODE_WATER;
2093 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2095 // this is the right thing to do for wateralpha
2096 GL_BlendFunc(GL_ONE, GL_ZERO);
2097 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2101 // this is the right thing to do for entity alpha
2102 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2103 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2106 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2108 mode = SHADERMODE_REFRACTION;
2109 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114 mode = SHADERMODE_GENERIC;
2115 permutation |= SHADERPERMUTATION_DIFFUSE;
2116 GL_BlendFunc(GL_ONE, GL_ZERO);
2117 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2120 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2122 if (r_glsl_offsetmapping.integer)
2124 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2125 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2126 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2127 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2128 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2130 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2131 if (r_glsl_offsetmapping_reliefmapping.integer)
2132 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2135 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2136 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2137 // normalmap (deferred prepass), may use alpha test on diffuse
2138 mode = SHADERMODE_DEFERREDGEOMETRY;
2139 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2140 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2141 GL_BlendFunc(GL_ONE, GL_ZERO);
2142 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2144 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2146 if (r_glsl_offsetmapping.integer)
2148 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2149 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2150 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2151 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2152 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2154 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2155 if (r_glsl_offsetmapping_reliefmapping.integer)
2156 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2159 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2160 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2162 mode = SHADERMODE_LIGHTSOURCE;
2163 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2164 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2165 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2166 permutation |= SHADERPERMUTATION_CUBEFILTER;
2167 if (diffusescale > 0)
2168 permutation |= SHADERPERMUTATION_DIFFUSE;
2169 if (specularscale > 0)
2170 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2171 if (r_refdef.fogenabled)
2172 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2173 if (rsurface.texture->colormapping)
2174 permutation |= SHADERPERMUTATION_COLORMAPPING;
2175 if (r_shadow_usingshadowmap2d)
2177 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2178 if(r_shadow_shadowmapvsdct)
2179 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2181 if (r_shadow_shadowmapsampler)
2182 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2183 if (r_shadow_shadowmappcf > 1)
2184 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2185 else if (r_shadow_shadowmappcf)
2186 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2188 if (rsurface.texture->reflectmasktexture)
2189 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2193 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2195 if (r_glsl_offsetmapping.integer)
2197 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2198 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2199 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2200 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2201 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2203 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2204 if (r_glsl_offsetmapping_reliefmapping.integer)
2205 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2208 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2209 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2210 // unshaded geometry (fullbright or ambient model lighting)
2211 mode = SHADERMODE_FLATCOLOR;
2212 ambientscale = diffusescale = specularscale = 0;
2213 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2214 permutation |= SHADERPERMUTATION_GLOW;
2215 if (r_refdef.fogenabled)
2216 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2217 if (rsurface.texture->colormapping)
2218 permutation |= SHADERPERMUTATION_COLORMAPPING;
2219 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2221 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2222 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2224 if (r_shadow_shadowmapsampler)
2225 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2226 if (r_shadow_shadowmappcf > 1)
2227 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2228 else if (r_shadow_shadowmappcf)
2229 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2232 permutation |= SHADERPERMUTATION_REFLECTION;
2233 if (rsurface.texture->reflectmasktexture)
2234 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2236 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2238 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2240 if (r_glsl_offsetmapping.integer)
2242 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2243 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2244 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2245 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2246 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2248 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2249 if (r_glsl_offsetmapping_reliefmapping.integer)
2250 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2253 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2254 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2255 // directional model lighting
2256 mode = SHADERMODE_LIGHTDIRECTION;
2257 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 permutation |= SHADERPERMUTATION_DIFFUSE;
2260 if (specularscale > 0)
2261 permutation |= SHADERPERMUTATION_SPECULAR;
2262 if (r_refdef.fogenabled)
2263 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2264 if (rsurface.texture->colormapping)
2265 permutation |= SHADERPERMUTATION_COLORMAPPING;
2266 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2268 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2269 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2271 if (r_shadow_shadowmapsampler)
2272 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2273 if (r_shadow_shadowmappcf > 1)
2274 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2275 else if (r_shadow_shadowmappcf)
2276 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2278 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2279 permutation |= SHADERPERMUTATION_REFLECTION;
2280 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2281 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2282 if (rsurface.texture->reflectmasktexture)
2283 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284 if (r_shadow_bouncegridtexture)
2286 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2287 if (r_shadow_bouncegriddirectional)
2288 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2290 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2295 if (r_glsl_offsetmapping.integer)
2297 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2298 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2299 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2300 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2301 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2303 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2304 if (r_glsl_offsetmapping_reliefmapping.integer)
2305 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2308 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2309 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2310 // ambient model lighting
2311 mode = SHADERMODE_LIGHTDIRECTION;
2312 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2313 permutation |= SHADERPERMUTATION_GLOW;
2314 if (r_refdef.fogenabled)
2315 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2316 if (rsurface.texture->colormapping)
2317 permutation |= SHADERPERMUTATION_COLORMAPPING;
2318 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2320 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2321 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2323 if (r_shadow_shadowmapsampler)
2324 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2325 if (r_shadow_shadowmappcf > 1)
2326 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2327 else if (r_shadow_shadowmappcf)
2328 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2330 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2331 permutation |= SHADERPERMUTATION_REFLECTION;
2332 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2333 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2334 if (rsurface.texture->reflectmasktexture)
2335 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336 if (r_shadow_bouncegridtexture)
2338 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2339 if (r_shadow_bouncegriddirectional)
2340 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2342 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2347 if (r_glsl_offsetmapping.integer)
2349 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2350 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2351 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2352 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2353 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2355 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2356 if (r_glsl_offsetmapping_reliefmapping.integer)
2357 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2360 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2363 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2364 permutation |= SHADERPERMUTATION_GLOW;
2365 if (r_refdef.fogenabled)
2366 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367 if (rsurface.texture->colormapping)
2368 permutation |= SHADERPERMUTATION_COLORMAPPING;
2369 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2371 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2374 if (r_shadow_shadowmapsampler)
2375 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2376 if (r_shadow_shadowmappcf > 1)
2377 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2378 else if (r_shadow_shadowmappcf)
2379 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2381 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2382 permutation |= SHADERPERMUTATION_REFLECTION;
2383 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2384 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2385 if (rsurface.texture->reflectmasktexture)
2386 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2387 if (FAKELIGHT_ENABLED)
2389 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2390 mode = SHADERMODE_FAKELIGHT;
2391 permutation |= SHADERPERMUTATION_DIFFUSE;
2392 if (specularscale > 0)
2393 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2397 // deluxemapping (light direction texture)
2398 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2399 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2401 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2402 permutation |= SHADERPERMUTATION_DIFFUSE;
2403 if (specularscale > 0)
2404 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2406 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2408 // fake deluxemapping (uniform light direction in tangentspace)
2409 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2410 permutation |= SHADERPERMUTATION_DIFFUSE;
2411 if (specularscale > 0)
2412 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2414 else if (rsurface.uselightmaptexture)
2416 // ordinary lightmapping (q1bsp, q3bsp)
2417 mode = SHADERMODE_LIGHTMAP;
2421 // ordinary vertex coloring (q3bsp)
2422 mode = SHADERMODE_VERTEXCOLOR;
2424 if (r_shadow_bouncegridtexture)
2426 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2427 if (r_shadow_bouncegriddirectional)
2428 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2430 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2433 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2434 colormod = dummy_colormod;
2435 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2436 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2437 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2438 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2439 switch(vid.renderpath)
2441 case RENDERPATH_D3D9:
2443 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2444 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2445 R_SetupShader_SetPermutationHLSL(mode, permutation);
2446 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2447 if (mode == SHADERMODE_LIGHTSOURCE)
2449 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2450 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2454 if (mode == SHADERMODE_LIGHTDIRECTION)
2456 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2459 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2460 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2461 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2462 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2463 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2465 if (mode == SHADERMODE_LIGHTSOURCE)
2467 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2468 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2469 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2470 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2471 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2473 // additive passes are only darkened by fog, not tinted
2474 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2475 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2479 if (mode == SHADERMODE_FLATCOLOR)
2481 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2483 else if (mode == SHADERMODE_LIGHTDIRECTION)
2485 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2487 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2488 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2489 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2491 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2495 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2496 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2497 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2498 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2499 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2501 // additive passes are only darkened by fog, not tinted
2502 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2503 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2505 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2506 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2507 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2508 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2509 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2510 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2511 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2512 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2513 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2514 if (mode == SHADERMODE_WATER)
2515 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2517 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2518 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2520 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2521 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2522 if (rsurface.texture->pantstexture)
2523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2526 if (rsurface.texture->shirttexture)
2527 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2529 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2530 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2532 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2533 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2534 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2535 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2536 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2538 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2539 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2540 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2541 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2542 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2543 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2544 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2545 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2546 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2547 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2548 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2549 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2550 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2551 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2552 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2553 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2554 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2555 if (rsurfacepass == RSURFPASS_BACKGROUND)
2557 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2558 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2559 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2563 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2565 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2566 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2567 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2568 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2569 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2571 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2572 if (rsurface.rtlight)
2574 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2575 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2580 case RENDERPATH_D3D10:
2581 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2583 case RENDERPATH_D3D11:
2584 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2586 case RENDERPATH_GL20:
2587 case RENDERPATH_GLES2:
2588 if (!vid.useinterleavedarrays)
2590 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2591 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2592 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2593 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2594 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2595 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2596 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2597 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2601 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2602 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2604 R_SetupShader_SetPermutationGLSL(mode, permutation);
2605 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2606 if (mode == SHADERMODE_LIGHTSOURCE)
2608 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2609 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2611 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2612 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2613 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2615 // additive passes are only darkened by fog, not tinted
2616 if (r_glsl_permutation->loc_FogColor >= 0)
2617 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2618 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2622 if (mode == SHADERMODE_FLATCOLOR)
2624 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2626 else if (mode == SHADERMODE_LIGHTDIRECTION)
2628 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2629 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2630 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2631 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2632 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2633 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2634 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2638 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2639 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2640 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2641 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2642 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2644 // additive passes are only darkened by fog, not tinted
2645 if (r_glsl_permutation->loc_FogColor >= 0)
2647 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2648 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2650 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2652 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2653 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2654 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2655 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2656 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2657 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2658 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2659 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2660 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2662 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2663 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2664 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2665 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2666 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2668 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2669 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2670 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2671 if (r_glsl_permutation->loc_Color_Pants >= 0)
2673 if (rsurface.texture->pantstexture)
2674 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2676 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2678 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2680 if (rsurface.texture->shirttexture)
2681 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2683 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2685 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2686 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2687 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2688 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2689 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2690 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2691 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2692 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2693 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2695 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2696 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2697 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2698 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2699 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2700 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2701 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2703 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2704 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2705 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2706 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2707 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2708 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2709 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2710 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2711 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2712 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2715 if (rsurfacepass == RSURFPASS_BACKGROUND)
2717 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2718 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2719 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2723 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2725 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2726 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2727 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2728 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2729 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2731 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2732 if (rsurface.rtlight)
2734 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2735 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2738 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2741 case RENDERPATH_GL13:
2742 case RENDERPATH_GL11:
2744 case RENDERPATH_SOFT:
2745 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2746 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747 R_SetupShader_SetPermutationSoft(mode, permutation);
2748 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749 if (mode == SHADERMODE_LIGHTSOURCE)
2751 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2758 // additive passes are only darkened by fog, not tinted
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2764 if (mode == SHADERMODE_FLATCOLOR)
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2768 else if (mode == SHADERMODE_LIGHTDIRECTION)
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2783 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2784 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2786 // additive passes are only darkened by fog, not tinted
2787 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2792 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2795 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2801 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2807 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2809 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2812 if (rsurface.texture->pantstexture)
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2815 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2817 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2819 if (rsurface.texture->shirttexture)
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2824 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2829 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2830 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2832 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2833 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2834 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2835 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2836 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2837 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2838 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2839 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2840 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2841 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2842 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2843 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2844 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2845 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2846 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2847 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2848 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2849 if (rsurfacepass == RSURFPASS_BACKGROUND)
2851 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2852 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2853 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2857 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2859 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2860 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2861 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2862 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2863 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2865 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2866 if (rsurface.rtlight)
2868 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2869 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2876 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2878 // select a permutation of the lighting shader appropriate to this
2879 // combination of texture, entity, light source, and fogging, only use the
2880 // minimum features necessary to avoid wasting rendering time in the
2881 // fragment shader on features that are not being used
2882 unsigned int permutation = 0;
2883 unsigned int mode = 0;
2884 const float *lightcolorbase = rtlight->currentcolor;
2885 float ambientscale = rtlight->ambientscale;
2886 float diffusescale = rtlight->diffusescale;
2887 float specularscale = rtlight->specularscale;
2888 // this is the location of the light in view space
2889 vec3_t viewlightorigin;
2890 // this transforms from view space (camera) to light space (cubemap)
2891 matrix4x4_t viewtolight;
2892 matrix4x4_t lighttoview;
2893 float viewtolight16f[16];
2894 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2896 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2897 if (rtlight->currentcubemap != r_texture_whitecube)
2898 permutation |= SHADERPERMUTATION_CUBEFILTER;
2899 if (diffusescale > 0)
2900 permutation |= SHADERPERMUTATION_DIFFUSE;
2901 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2902 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2903 if (r_shadow_usingshadowmap2d)
2905 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2906 if (r_shadow_shadowmapvsdct)
2907 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2909 if (r_shadow_shadowmapsampler)
2910 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2911 if (r_shadow_shadowmappcf > 1)
2912 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2913 else if (r_shadow_shadowmappcf)
2914 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2916 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2917 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2918 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2919 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2920 switch(vid.renderpath)
2922 case RENDERPATH_D3D9:
2924 R_SetupShader_SetPermutationHLSL(mode, permutation);
2925 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2926 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2927 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2928 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2929 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2930 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2931 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2932 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2933 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2934 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2936 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2937 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2938 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2939 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2940 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2941 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2944 case RENDERPATH_D3D10:
2945 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2947 case RENDERPATH_D3D11:
2948 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2950 case RENDERPATH_GL20:
2951 case RENDERPATH_GLES2:
2952 R_SetupShader_SetPermutationGLSL(mode, permutation);
2953 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2954 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2955 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2956 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2957 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2958 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2959 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2960 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2961 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2962 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2964 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2965 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2966 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2967 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2968 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2969 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2971 case RENDERPATH_GL13:
2972 case RENDERPATH_GL11:
2974 case RENDERPATH_SOFT:
2975 R_SetupShader_SetPermutationGLSL(mode, permutation);
2976 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2977 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2978 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2979 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2980 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2981 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2982 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2983 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2984 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2985 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2987 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2988 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2989 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2990 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2991 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2992 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2997 #define SKINFRAME_HASH 1024
3001 int loadsequence; // incremented each level change
3002 memexpandablearray_t array;
3003 skinframe_t *hash[SKINFRAME_HASH];
3006 r_skinframe_t r_skinframe;
3008 void R_SkinFrame_PrepareForPurge(void)
3010 r_skinframe.loadsequence++;
3011 // wrap it without hitting zero
3012 if (r_skinframe.loadsequence >= 200)
3013 r_skinframe.loadsequence = 1;
3016 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3020 // mark the skinframe as used for the purging code
3021 skinframe->loadsequence = r_skinframe.loadsequence;
3024 void R_SkinFrame_Purge(void)
3028 for (i = 0;i < SKINFRAME_HASH;i++)
3030 for (s = r_skinframe.hash[i];s;s = s->next)
3032 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3034 if (s->merged == s->base)
3036 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3037 R_PurgeTexture(s->stain );s->stain = NULL;
3038 R_PurgeTexture(s->merged);s->merged = NULL;
3039 R_PurgeTexture(s->base );s->base = NULL;
3040 R_PurgeTexture(s->pants );s->pants = NULL;
3041 R_PurgeTexture(s->shirt );s->shirt = NULL;
3042 R_PurgeTexture(s->nmap );s->nmap = NULL;
3043 R_PurgeTexture(s->gloss );s->gloss = NULL;
3044 R_PurgeTexture(s->glow );s->glow = NULL;
3045 R_PurgeTexture(s->fog );s->fog = NULL;
3046 R_PurgeTexture(s->reflect);s->reflect = NULL;
3047 s->loadsequence = 0;
3053 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3055 char basename[MAX_QPATH];
3057 Image_StripImageExtension(name, basename, sizeof(basename));
3059 if( last == NULL ) {
3061 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3062 item = r_skinframe.hash[hashindex];
3067 // linearly search through the hash bucket
3068 for( ; item ; item = item->next ) {
3069 if( !strcmp( item->basename, basename ) ) {
3076 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3080 char basename[MAX_QPATH];
3082 Image_StripImageExtension(name, basename, sizeof(basename));
3084 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3085 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3086 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3090 rtexture_t *dyntexture;
3091 // check whether its a dynamic texture
3092 dyntexture = CL_GetDynTexture( basename );
3093 if (!add && !dyntexture)
3095 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3096 memset(item, 0, sizeof(*item));
3097 strlcpy(item->basename, basename, sizeof(item->basename));
3098 item->base = dyntexture; // either NULL or dyntexture handle
3099 item->textureflags = textureflags;
3100 item->comparewidth = comparewidth;
3101 item->compareheight = compareheight;
3102 item->comparecrc = comparecrc;
3103 item->next = r_skinframe.hash[hashindex];
3104 r_skinframe.hash[hashindex] = item;
3106 else if( item->base == NULL )
3108 rtexture_t *dyntexture;
3109 // check whether its a dynamic texture
3110 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3111 dyntexture = CL_GetDynTexture( basename );
3112 item->base = dyntexture; // either NULL or dyntexture handle
3115 R_SkinFrame_MarkUsed(item);
3119 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3121 unsigned long long avgcolor[5], wsum; \
3129 for(pix = 0; pix < cnt; ++pix) \
3132 for(comp = 0; comp < 3; ++comp) \
3134 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3137 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3139 for(comp = 0; comp < 3; ++comp) \
3140 avgcolor[comp] += getpixel * w; \
3143 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144 avgcolor[4] += getpixel; \
3146 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3148 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3149 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3150 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3151 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3154 extern cvar_t gl_picmip;
3155 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3158 unsigned char *pixels;
3159 unsigned char *bumppixels;
3160 unsigned char *basepixels = NULL;
3161 int basepixels_width = 0;
3162 int basepixels_height = 0;
3163 skinframe_t *skinframe;
3164 rtexture_t *ddsbase = NULL;
3165 qboolean ddshasalpha = false;
3166 float ddsavgcolor[4];
3167 char basename[MAX_QPATH];
3168 int miplevel = R_PicmipForFlags(textureflags);
3169 int savemiplevel = miplevel;
3172 if (cls.state == ca_dedicated)
3175 // return an existing skinframe if already loaded
3176 // if loading of the first image fails, don't make a new skinframe as it
3177 // would cause all future lookups of this to be missing
3178 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3179 if (skinframe && skinframe->base)
3182 Image_StripImageExtension(name, basename, sizeof(basename));
3184 // check for DDS texture file first
3185 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3187 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3188 if (basepixels == NULL)
3192 // FIXME handle miplevel
3194 if (developer_loading.integer)
3195 Con_Printf("loading skin \"%s\"\n", name);
3197 // we've got some pixels to store, so really allocate this new texture now
3199 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3200 skinframe->stain = NULL;
3201 skinframe->merged = NULL;
3202 skinframe->base = NULL;
3203 skinframe->pants = NULL;
3204 skinframe->shirt = NULL;
3205 skinframe->nmap = NULL;
3206 skinframe->gloss = NULL;
3207 skinframe->glow = NULL;
3208 skinframe->fog = NULL;
3209 skinframe->reflect = NULL;
3210 skinframe->hasalpha = false;
3214 skinframe->base = ddsbase;
3215 skinframe->hasalpha = ddshasalpha;
3216 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3217 if (r_loadfog && skinframe->hasalpha)
3218 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3219 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3223 basepixels_width = image_width;
3224 basepixels_height = image_height;
3225 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3226 if (textureflags & TEXF_ALPHA)
3228 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3230 if (basepixels[j] < 255)
3232 skinframe->hasalpha = true;
3236 if (r_loadfog && skinframe->hasalpha)
3238 // has transparent pixels
3239 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3240 for (j = 0;j < image_width * image_height * 4;j += 4)
3245 pixels[j+3] = basepixels[j+3];
3247 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3251 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3252 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3253 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3254 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3255 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3256 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3261 mymiplevel = savemiplevel;
3262 if (r_loadnormalmap)
3263 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3264 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3266 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 // _norm is the name used by tenebrae and has been adopted as standard
3273 if (r_loadnormalmap && skinframe->nmap == NULL)
3275 mymiplevel = savemiplevel;
3276 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3278 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3282 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3284 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3285 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3286 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3288 Mem_Free(bumppixels);
3290 else if (r_shadow_bumpscale_basetexture.value > 0)
3292 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3293 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3294 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3297 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3298 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3301 // _luma is supported only for tenebrae compatibility
3302 // _glow is the preferred name
3303 mymiplevel = savemiplevel;
3304 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3306 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3307 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3308 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3309 Mem_Free(pixels);pixels = NULL;
3312 mymiplevel = savemiplevel;
3313 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3315 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3316 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3317 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3322 mymiplevel = savemiplevel;
3323 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3325 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3326 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3327 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3332 mymiplevel = savemiplevel;
3333 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3335 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3336 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3337 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3342 mymiplevel = savemiplevel;
3343 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3345 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3346 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3347 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3353 Mem_Free(basepixels);
3358 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3359 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3362 unsigned char *temp1, *temp2;
3363 skinframe_t *skinframe;
3365 if (cls.state == ca_dedicated)
3368 // if already loaded just return it, otherwise make a new skinframe
3369 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3370 if (skinframe && skinframe->base)
3373 skinframe->stain = NULL;
3374 skinframe->merged = NULL;
3375 skinframe->base = NULL;
3376 skinframe->pants = NULL;
3377 skinframe->shirt = NULL;
3378 skinframe->nmap = NULL;
3379 skinframe->gloss = NULL;
3380 skinframe->glow = NULL;
3381 skinframe->fog = NULL;
3382 skinframe->reflect = NULL;
3383 skinframe->hasalpha = false;
3385 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3389 if (developer_loading.integer)
3390 Con_Printf("loading 32bit skin \"%s\"\n", name);
3392 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3394 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3395 temp2 = temp1 + width * height * 4;
3396 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3397 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3400 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3401 if (textureflags & TEXF_ALPHA)
3403 for (i = 3;i < width * height * 4;i += 4)
3405 if (skindata[i] < 255)
3407 skinframe->hasalpha = true;
3411 if (r_loadfog && skinframe->hasalpha)
3413 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3414 memcpy(fogpixels, skindata, width * height * 4);
3415 for (i = 0;i < width * height * 4;i += 4)
3416 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3417 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3418 Mem_Free(fogpixels);
3422 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3423 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3428 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3432 skinframe_t *skinframe;
3434 if (cls.state == ca_dedicated)
3437 // if already loaded just return it, otherwise make a new skinframe
3438 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3439 if (skinframe && skinframe->base)
3442 skinframe->stain = NULL;
3443 skinframe->merged = NULL;
3444 skinframe->base = NULL;
3445 skinframe->pants = NULL;
3446 skinframe->shirt = NULL;
3447 skinframe->nmap = NULL;
3448 skinframe->gloss = NULL;
3449 skinframe->glow = NULL;
3450 skinframe->fog = NULL;
3451 skinframe->reflect = NULL;
3452 skinframe->hasalpha = false;
3454 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3458 if (developer_loading.integer)
3459 Con_Printf("loading quake skin \"%s\"\n", name);
3461 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3462 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3463 memcpy(skinframe->qpixels, skindata, width*height);
3464 skinframe->qwidth = width;
3465 skinframe->qheight = height;
3468 for (i = 0;i < width * height;i++)
3469 featuresmask |= palette_featureflags[skindata[i]];
3471 skinframe->hasalpha = false;
3472 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3473 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3474 skinframe->qgeneratemerged = true;
3475 skinframe->qgeneratebase = skinframe->qhascolormapping;
3476 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3478 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3479 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3484 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3488 unsigned char *skindata;
3490 if (!skinframe->qpixels)
3493 if (!skinframe->qhascolormapping)
3494 colormapped = false;
3498 if (!skinframe->qgeneratebase)
3503 if (!skinframe->qgeneratemerged)
3507 width = skinframe->qwidth;
3508 height = skinframe->qheight;
3509 skindata = skinframe->qpixels;
3511 if (skinframe->qgeneratenmap)
3513 unsigned char *temp1, *temp2;
3514 skinframe->qgeneratenmap = false;
3515 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3516 temp2 = temp1 + width * height * 4;
3517 // use either a custom palette or the quake palette
3518 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3519 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3520 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3524 if (skinframe->qgenerateglow)
3526 skinframe->qgenerateglow = false;
3527 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3532 skinframe->qgeneratebase = false;
3533 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3534 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3535 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3539 skinframe->qgeneratemerged = false;
3540 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3543 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3545 Mem_Free(skinframe->qpixels);
3546 skinframe->qpixels = NULL;
3550 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3553 skinframe_t *skinframe;
3555 if (cls.state == ca_dedicated)
3558 // if already loaded just return it, otherwise make a new skinframe
3559 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3560 if (skinframe && skinframe->base)
3563 skinframe->stain = NULL;
3564 skinframe->merged = NULL;
3565 skinframe->base = NULL;
3566 skinframe->pants = NULL;
3567 skinframe->shirt = NULL;
3568 skinframe->nmap = NULL;
3569 skinframe->gloss = NULL;
3570 skinframe->glow = NULL;
3571 skinframe->fog = NULL;
3572 skinframe->reflect = NULL;
3573 skinframe->hasalpha = false;
3575 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3579 if (developer_loading.integer)
3580 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3582 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3583 if (textureflags & TEXF_ALPHA)
3585 for (i = 0;i < width * height;i++)
3587 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3589 skinframe->hasalpha = true;
3593 if (r_loadfog && skinframe->hasalpha)
3594 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3597 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3598 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3603 skinframe_t *R_SkinFrame_LoadMissing(void)
3605 skinframe_t *skinframe;
3607 if (cls.state == ca_dedicated)
3610 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3611 skinframe->stain = NULL;
3612 skinframe->merged = NULL;
3613 skinframe->base = NULL;
3614 skinframe->pants = NULL;
3615 skinframe->shirt = NULL;
3616 skinframe->nmap = NULL;
3617 skinframe->gloss = NULL;
3618 skinframe->glow = NULL;
3619 skinframe->fog = NULL;
3620 skinframe->reflect = NULL;
3621 skinframe->hasalpha = false;
3623 skinframe->avgcolor[0] = rand() / RAND_MAX;
3624 skinframe->avgcolor[1] = rand() / RAND_MAX;
3625 skinframe->avgcolor[2] = rand() / RAND_MAX;
3626 skinframe->avgcolor[3] = 1;
3631 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3632 typedef struct suffixinfo_s
3635 qboolean flipx, flipy, flipdiagonal;
3638 static suffixinfo_t suffix[3][6] =
3641 {"px", false, false, false},
3642 {"nx", false, false, false},
3643 {"py", false, false, false},
3644 {"ny", false, false, false},
3645 {"pz", false, false, false},
3646 {"nz", false, false, false}
3649 {"posx", false, false, false},
3650 {"negx", false, false, false},
3651 {"posy", false, false, false},
3652 {"negy", false, false, false},
3653 {"posz", false, false, false},
3654 {"negz", false, false, false}
3657 {"rt", true, false, true},
3658 {"lf", false, true, true},
3659 {"ft", true, true, false},
3660 {"bk", false, false, false},
3661 {"up", true, false, true},
3662 {"dn", true, false, true}
3666 static int componentorder[4] = {0, 1, 2, 3};
3668 rtexture_t *R_LoadCubemap(const char *basename)
3670 int i, j, cubemapsize;
3671 unsigned char *cubemappixels, *image_buffer;
3672 rtexture_t *cubemaptexture;
3674 // must start 0 so the first loadimagepixels has no requested width/height
3676 cubemappixels = NULL;
3677 cubemaptexture = NULL;
3678 // keep trying different suffix groups (posx, px, rt) until one loads
3679 for (j = 0;j < 3 && !cubemappixels;j++)
3681 // load the 6 images in the suffix group
3682 for (i = 0;i < 6;i++)
3684 // generate an image name based on the base and and suffix
3685 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3687 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3689 // an image loaded, make sure width and height are equal
3690 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3692 // if this is the first image to load successfully, allocate the cubemap memory
3693 if (!cubemappixels && image_width >= 1)
3695 cubemapsize = image_width;
3696 // note this clears to black, so unavailable sides are black
3697 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3699 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3701 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3704 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3706 Mem_Free(image_buffer);
3710 // if a cubemap loaded, upload it
3713 if (developer_loading.integer)
3714 Con_Printf("loading cubemap \"%s\"\n", basename);
3716 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3717 Mem_Free(cubemappixels);
3721 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3722 if (developer_loading.integer)
3724 Con_Printf("(tried tried images ");
3725 for (j = 0;j < 3;j++)
3726 for (i = 0;i < 6;i++)
3727 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3728 Con_Print(" and was unable to find any of them).\n");
3731 return cubemaptexture;
3734 rtexture_t *R_GetCubemap(const char *basename)
3737 for (i = 0;i < r_texture_numcubemaps;i++)
3738 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3739 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3740 if (i >= MAX_CUBEMAPS)
3741 return r_texture_whitecube;
3742 r_texture_numcubemaps++;
3743 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3744 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3745 return r_texture_cubemaps[i].texture;
3748 void R_FreeCubemaps(void)
3751 for (i = 0;i < r_texture_numcubemaps;i++)
3753 if (developer_loading.integer)
3754 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3755 if (r_texture_cubemaps[i].texture)
3756 R_FreeTexture(r_texture_cubemaps[i].texture);
3758 r_texture_numcubemaps = 0;
3761 void R_Main_FreeViewCache(void)
3763 if (r_refdef.viewcache.entityvisible)
3764 Mem_Free(r_refdef.viewcache.entityvisible);
3765 if (r_refdef.viewcache.world_pvsbits)
3766 Mem_Free(r_refdef.viewcache.world_pvsbits);
3767 if (r_refdef.viewcache.world_leafvisible)
3768 Mem_Free(r_refdef.viewcache.world_leafvisible);
3769 if (r_refdef.viewcache.world_surfacevisible)
3770 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3771 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3774 void R_Main_ResizeViewCache(void)
3776 int numentities = r_refdef.scene.numentities;
3777 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3778 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3779 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3780 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3781 if (r_refdef.viewcache.maxentities < numentities)
3783 r_refdef.viewcache.maxentities = numentities;
3784 if (r_refdef.viewcache.entityvisible)
3785 Mem_Free(r_refdef.viewcache.entityvisible);
3786 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3788 if (r_refdef.viewcache.world_numclusters != numclusters)
3790 r_refdef.viewcache.world_numclusters = numclusters;
3791 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3792 if (r_refdef.viewcache.world_pvsbits)
3793 Mem_Free(r_refdef.viewcache.world_pvsbits);
3794 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3796 if (r_refdef.viewcache.world_numleafs != numleafs)
3798 r_refdef.viewcache.world_numleafs = numleafs;
3799 if (r_refdef.viewcache.world_leafvisible)
3800 Mem_Free(r_refdef.viewcache.world_leafvisible);
3801 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3803 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3805 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3806 if (r_refdef.viewcache.world_surfacevisible)
3807 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3808 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3812 extern rtexture_t *loadingscreentexture;
3813 void gl_main_start(void)
3815 loadingscreentexture = NULL;
3816 r_texture_blanknormalmap = NULL;
3817 r_texture_white = NULL;
3818 r_texture_grey128 = NULL;
3819 r_texture_black = NULL;
3820 r_texture_whitecube = NULL;
3821 r_texture_normalizationcube = NULL;
3822 r_texture_fogattenuation = NULL;
3823 r_texture_fogheighttexture = NULL;
3824 r_texture_gammaramps = NULL;
3825 r_texture_numcubemaps = 0;
3827 r_loaddds = r_texture_dds_load.integer != 0;
3828 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3830 switch(vid.renderpath)
3832 case RENDERPATH_GL20:
3833 case RENDERPATH_D3D9:
3834 case RENDERPATH_D3D10:
3835 case RENDERPATH_D3D11:
3836 case RENDERPATH_SOFT:
3837 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3838 Cvar_SetValueQuick(&gl_combine, 1);
3839 Cvar_SetValueQuick(&r_glsl, 1);
3840 r_loadnormalmap = true;
3844 case RENDERPATH_GL13:
3845 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3846 Cvar_SetValueQuick(&gl_combine, 1);
3847 Cvar_SetValueQuick(&r_glsl, 0);
3848 r_loadnormalmap = false;
3849 r_loadgloss = false;
3852 case RENDERPATH_GL11:
3853 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3854 Cvar_SetValueQuick(&gl_combine, 0);
3855 Cvar_SetValueQuick(&r_glsl, 0);
3856 r_loadnormalmap = false;
3857 r_loadgloss = false;
3860 case RENDERPATH_GLES2:
3861 Cvar_SetValueQuick(&r_textureunits, 1);
3862 Cvar_SetValueQuick(&gl_combine, 1);
3863 Cvar_SetValueQuick(&r_glsl, 1);
3864 r_loadnormalmap = true;
3865 r_loadgloss = false;
3871 R_FrameData_Reset();
3875 memset(r_queries, 0, sizeof(r_queries));
3877 r_qwskincache = NULL;
3878 r_qwskincache_size = 0;
3880 // due to caching of texture_t references, the collision cache must be reset
3881 Collision_Cache_Reset(true);
3883 // set up r_skinframe loading system for textures
3884 memset(&r_skinframe, 0, sizeof(r_skinframe));
3885 r_skinframe.loadsequence = 1;
3886 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3888 r_main_texturepool = R_AllocTexturePool();
3889 R_BuildBlankTextures();
3891 if (vid.support.arb_texture_cube_map)
3894 R_BuildNormalizationCube();
3896 r_texture_fogattenuation = NULL;
3897 r_texture_fogheighttexture = NULL;
3898 r_texture_gammaramps = NULL;
3899 //r_texture_fogintensity = NULL;
3900 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3901 memset(&r_waterstate, 0, sizeof(r_waterstate));
3902 r_glsl_permutation = NULL;
3903 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3904 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3905 glslshaderstring = NULL;
3907 r_hlsl_permutation = NULL;
3908 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3909 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3911 hlslshaderstring = NULL;
3912 memset(&r_svbsp, 0, sizeof (r_svbsp));
3914 r_refdef.fogmasktable_density = 0;
3917 void gl_main_shutdown(void)
3920 R_FrameData_Reset();
3922 R_Main_FreeViewCache();
3924 switch(vid.renderpath)
3926 case RENDERPATH_GL11:
3927 case RENDERPATH_GL13:
3928 case RENDERPATH_GL20:
3929 case RENDERPATH_GLES2:
3931 qglDeleteQueriesARB(r_maxqueries, r_queries);
3933 case RENDERPATH_D3D9:
3934 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3936 case RENDERPATH_D3D10:
3937 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3939 case RENDERPATH_D3D11:
3940 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942 case RENDERPATH_SOFT:
3948 memset(r_queries, 0, sizeof(r_queries));
3950 r_qwskincache = NULL;
3951 r_qwskincache_size = 0;
3953 // clear out the r_skinframe state
3954 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3955 memset(&r_skinframe, 0, sizeof(r_skinframe));
3958 Mem_Free(r_svbsp.nodes);
3959 memset(&r_svbsp, 0, sizeof (r_svbsp));
3960 R_FreeTexturePool(&r_main_texturepool);
3961 loadingscreentexture = NULL;
3962 r_texture_blanknormalmap = NULL;
3963 r_texture_white = NULL;
3964 r_texture_grey128 = NULL;
3965 r_texture_black = NULL;
3966 r_texture_whitecube = NULL;
3967 r_texture_normalizationcube = NULL;
3968 r_texture_fogattenuation = NULL;
3969 r_texture_fogheighttexture = NULL;
3970 r_texture_gammaramps = NULL;
3971 r_texture_numcubemaps = 0;
3972 //r_texture_fogintensity = NULL;
3973 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3974 memset(&r_waterstate, 0, sizeof(r_waterstate));
3977 r_glsl_permutation = NULL;
3978 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3979 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3980 glslshaderstring = NULL;
3982 r_hlsl_permutation = NULL;
3983 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3984 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3986 hlslshaderstring = NULL;
3989 extern void CL_ParseEntityLump(char *entitystring);
3990 void gl_main_newmap(void)
3992 // FIXME: move this code to client
3993 char *entities, entname[MAX_QPATH];
3995 Mem_Free(r_qwskincache);
3996 r_qwskincache = NULL;
3997 r_qwskincache_size = 0;
4000 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4001 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4003 CL_ParseEntityLump(entities);
4007 if (cl.worldmodel->brush.entities)
4008 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4010 R_Main_FreeViewCache();
4012 R_FrameData_Reset();
4015 void GL_Main_Init(void)
4017 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4019 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4020 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4021 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4022 if (gamemode == GAME_NEHAHRA)
4024 Cvar_RegisterVariable (&gl_fogenable);
4025 Cvar_RegisterVariable (&gl_fogdensity);
4026 Cvar_RegisterVariable (&gl_fogred);
4027 Cvar_RegisterVariable (&gl_foggreen);
4028 Cvar_RegisterVariable (&gl_fogblue);
4029 Cvar_RegisterVariable (&gl_fogstart);
4030 Cvar_RegisterVariable (&gl_fogend);
4031 Cvar_RegisterVariable (&gl_skyclip);
4033 Cvar_RegisterVariable(&r_motionblur);
4034 Cvar_RegisterVariable(&r_motionblur_maxblur);
4035 Cvar_RegisterVariable(&r_motionblur_bmin);
4036 Cvar_RegisterVariable(&r_motionblur_vmin);
4037 Cvar_RegisterVariable(&r_motionblur_vmax);
4038 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4039 Cvar_RegisterVariable(&r_motionblur_randomize);
4040 Cvar_RegisterVariable(&r_damageblur);
4041 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4042 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4043 Cvar_RegisterVariable(&r_equalize_entities_by);
4044 Cvar_RegisterVariable(&r_equalize_entities_to);
4045 Cvar_RegisterVariable(&r_depthfirst);
4046 Cvar_RegisterVariable(&r_useinfinitefarclip);
4047 Cvar_RegisterVariable(&r_farclip_base);
4048 Cvar_RegisterVariable(&r_farclip_world);
4049 Cvar_RegisterVariable(&r_nearclip);
4050 Cvar_RegisterVariable(&r_showbboxes);
4051 Cvar_RegisterVariable(&r_showsurfaces);
4052 Cvar_RegisterVariable(&r_showtris);
4053 Cvar_RegisterVariable(&r_shownormals);
4054 Cvar_RegisterVariable(&r_showlighting);
4055 Cvar_RegisterVariable(&r_showshadowvolumes);
4056 Cvar_RegisterVariable(&r_showcollisionbrushes);
4057 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4058 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4059 Cvar_RegisterVariable(&r_showdisabledepthtest);
4060 Cvar_RegisterVariable(&r_drawportals);
4061 Cvar_RegisterVariable(&r_drawentities);
4062 Cvar_RegisterVariable(&r_draw2d);
4063 Cvar_RegisterVariable(&r_drawworld);
4064 Cvar_RegisterVariable(&r_cullentities_trace);
4065 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4066 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4067 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4068 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4069 Cvar_RegisterVariable(&r_drawviewmodel);
4070 Cvar_RegisterVariable(&r_drawexteriormodel);
4071 Cvar_RegisterVariable(&r_speeds);
4072 Cvar_RegisterVariable(&r_fullbrights);
4073 Cvar_RegisterVariable(&r_wateralpha);
4074 Cvar_RegisterVariable(&r_dynamic);
4075 Cvar_RegisterVariable(&r_fakelight);
4076 Cvar_RegisterVariable(&r_fakelight_intensity);
4077 Cvar_RegisterVariable(&r_fullbright);
4078 Cvar_RegisterVariable(&r_shadows);
4079 Cvar_RegisterVariable(&r_shadows_darken);
4080 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4081 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4082 Cvar_RegisterVariable(&r_shadows_throwdistance);
4083 Cvar_RegisterVariable(&r_shadows_throwdirection);
4084 Cvar_RegisterVariable(&r_shadows_focus);
4085 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4086 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4087 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4088 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4089 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4090 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4091 Cvar_RegisterVariable(&r_fog_exp2);
4092 Cvar_RegisterVariable(&r_fog_clear);
4093 Cvar_RegisterVariable(&r_drawfog);
4094 Cvar_RegisterVariable(&r_transparentdepthmasking);
4095 Cvar_RegisterVariable(&r_texture_dds_load);
4096 Cvar_RegisterVariable(&r_texture_dds_save);
4097 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4098 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4099 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4100 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4101 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4102 Cvar_RegisterVariable(&r_textureunits);
4103 Cvar_RegisterVariable(&gl_combine);
4104 Cvar_RegisterVariable(&r_viewfbo);
4105 Cvar_RegisterVariable(&r_viewscale);
4106 Cvar_RegisterVariable(&r_glsl);
4107 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4108 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4109 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4110 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4111 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4112 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4113 Cvar_RegisterVariable(&r_glsl_postprocess);
4114 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4115 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4116 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4117 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4118 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4119 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4120 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4121 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4123 Cvar_RegisterVariable(&r_water);
4124 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4125 Cvar_RegisterVariable(&r_water_clippingplanebias);
4126 Cvar_RegisterVariable(&r_water_refractdistort);
4127 Cvar_RegisterVariable(&r_water_reflectdistort);
4128 Cvar_RegisterVariable(&r_water_scissormode);
4129 Cvar_RegisterVariable(&r_lerpsprites);
4130 Cvar_RegisterVariable(&r_lerpmodels);
4131 Cvar_RegisterVariable(&r_lerplightstyles);
4132 Cvar_RegisterVariable(&r_waterscroll);
4133 Cvar_RegisterVariable(&r_bloom);
4134 Cvar_RegisterVariable(&r_bloom_colorscale);
4135 Cvar_RegisterVariable(&r_bloom_brighten);
4136 Cvar_RegisterVariable(&r_bloom_blur);
4137 Cvar_RegisterVariable(&r_bloom_resolution);
4138 Cvar_RegisterVariable(&r_bloom_colorexponent);
4139 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4140 Cvar_RegisterVariable(&r_hdr);
4141 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4142 Cvar_RegisterVariable(&r_hdr_glowintensity);
4143 Cvar_RegisterVariable(&r_hdr_range);
4144 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4145 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4146 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4147 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4148 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4149 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4150 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4151 Cvar_RegisterVariable(&developer_texturelogging);
4152 Cvar_RegisterVariable(&gl_lightmaps);
4153 Cvar_RegisterVariable(&r_test);
4154 Cvar_RegisterVariable(&r_glsl_saturation);
4155 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4156 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4157 Cvar_RegisterVariable(&r_framedatasize);
4158 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4159 Cvar_SetValue("r_fullbrights", 0);
4160 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4162 Cvar_RegisterVariable(&r_track_sprites);
4163 Cvar_RegisterVariable(&r_track_sprites_flags);
4164 Cvar_RegisterVariable(&r_track_sprites_scalew);
4165 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4166 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4167 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4168 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4169 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4172 extern void R_Textures_Init(void);
4173 extern void GL_Draw_Init(void);
4174 extern void GL_Main_Init(void);
4175 extern void R_Shadow_Init(void);
4176 extern void R_Sky_Init(void);
4177 extern void GL_Surf_Init(void);
4178 extern void R_Particles_Init(void);
4179 extern void R_Explosion_Init(void);
4180 extern void gl_backend_init(void);
4181 extern void Sbar_Init(void);
4182 extern void R_LightningBeams_Init(void);
4183 extern void Mod_RenderInit(void);
4184 extern void Font_Init(void);
4186 void Render_Init(void)
4199 R_LightningBeams_Init();
4208 extern char *ENGINE_EXTENSIONS;
4211 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4212 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4213 gl_version = (const char *)qglGetString(GL_VERSION);
4214 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4218 if (!gl_platformextensions)
4219 gl_platformextensions = "";
4221 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4222 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4223 Con_Printf("GL_VERSION: %s\n", gl_version);
4224 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4225 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4227 VID_CheckExtensions();
4229 // LordHavoc: report supported extensions
4230 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4232 // clear to black (loading plaque will be seen over this)
4233 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4236 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4240 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4242 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4245 p = r_refdef.view.frustum + i;
4250 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4254 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4258 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4262 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4266 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4270 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4274 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4278 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4286 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4290 for (i = 0;i < numplanes;i++)
4297 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4301 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4305 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4309 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4313 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4317 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4321 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4325 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4333 //==================================================================================
4335 // LordHavoc: this stores temporary data used within the same frame
4337 typedef struct r_framedata_mem_s
4339 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4340 size_t size; // how much usable space
4341 size_t current; // how much space in use
4342 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4343 size_t wantedsize; // how much space was allocated
4344 unsigned char *data; // start of real data (16byte aligned)
4348 static r_framedata_mem_t *r_framedata_mem;
4350 void R_FrameData_Reset(void)
4352 while (r_framedata_mem)
4354 r_framedata_mem_t *next = r_framedata_mem->purge;
4355 Mem_Free(r_framedata_mem);
4356 r_framedata_mem = next;
4360 void R_FrameData_Resize(void)
4363 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4364 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4365 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4367 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4368 newmem->wantedsize = wantedsize;
4369 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4370 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4371 newmem->current = 0;
4373 newmem->purge = r_framedata_mem;
4374 r_framedata_mem = newmem;
4378 void R_FrameData_NewFrame(void)
4380 R_FrameData_Resize();
4381 if (!r_framedata_mem)
4383 // if we ran out of space on the last frame, free the old memory now
4384 while (r_framedata_mem->purge)
4386 // repeatedly remove the second item in the list, leaving only head
4387 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4388 Mem_Free(r_framedata_mem->purge);
4389 r_framedata_mem->purge = next;
4391 // reset the current mem pointer
4392 r_framedata_mem->current = 0;
4393 r_framedata_mem->mark = 0;
4396 void *R_FrameData_Alloc(size_t size)
4400 // align to 16 byte boundary - the data pointer is already aligned, so we
4401 // only need to ensure the size of every allocation is also aligned
4402 size = (size + 15) & ~15;
4404 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4406 // emergency - we ran out of space, allocate more memory
4407 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4408 R_FrameData_Resize();
4411 data = r_framedata_mem->data + r_framedata_mem->current;
4412 r_framedata_mem->current += size;
4414 // count the usage for stats
4415 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4416 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4418 return (void *)data;
4421 void *R_FrameData_Store(size_t size, void *data)
4423 void *d = R_FrameData_Alloc(size);
4425 memcpy(d, data, size);
4429 void R_FrameData_SetMark(void)
4431 if (!r_framedata_mem)
4433 r_framedata_mem->mark = r_framedata_mem->current;
4436 void R_FrameData_ReturnToMark(void)
4438 if (!r_framedata_mem)
4440 r_framedata_mem->current = r_framedata_mem->mark;
4443 //==================================================================================
4445 // LordHavoc: animcache originally written by Echon, rewritten since then
4448 * Animation cache prevents re-generating mesh data for an animated model
4449 * multiple times in one frame for lighting, shadowing, reflections, etc.
4452 void R_AnimCache_Free(void)
4456 void R_AnimCache_ClearCache(void)
4459 entity_render_t *ent;
4461 for (i = 0;i < r_refdef.scene.numentities;i++)
4463 ent = r_refdef.scene.entities[i];
4464 ent->animcache_vertex3f = NULL;
4465 ent->animcache_normal3f = NULL;
4466 ent->animcache_svector3f = NULL;
4467 ent->animcache_tvector3f = NULL;
4468 ent->animcache_vertexmesh = NULL;
4469 ent->animcache_vertex3fbuffer = NULL;
4470 ent->animcache_vertexmeshbuffer = NULL;
4474 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4478 // check if we need the meshbuffers
4479 if (!vid.useinterleavedarrays)
4482 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4483 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4484 // TODO: upload vertex3f buffer?
4485 if (ent->animcache_vertexmesh)
4487 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4488 for (i = 0;i < numvertices;i++)
4489 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4490 if (ent->animcache_svector3f)
4491 for (i = 0;i < numvertices;i++)
4492 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4493 if (ent->animcache_tvector3f)
4494 for (i = 0;i < numvertices;i++)
4495 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4496 if (ent->animcache_normal3f)
4497 for (i = 0;i < numvertices;i++)
4498 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4499 // TODO: upload vertexmeshbuffer?
4503 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4505 dp_model_t *model = ent->model;
4507 // see if it's already cached this frame
4508 if (ent->animcache_vertex3f)
4510 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4511 if (wantnormals || wanttangents)
4513 if (ent->animcache_normal3f)
4514 wantnormals = false;
4515 if (ent->animcache_svector3f)
4516 wanttangents = false;
4517 if (wantnormals || wanttangents)
4519 numvertices = model->surfmesh.num_vertices;
4521 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4524 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4525 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4527 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4528 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4534 // see if this ent is worth caching
4535 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4537 // get some memory for this entity and generate mesh data
4538 numvertices = model->surfmesh.num_vertices;
4539 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4541 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4544 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4545 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4548 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4553 void R_AnimCache_CacheVisibleEntities(void)
4556 qboolean wantnormals = true;
4557 qboolean wanttangents = !r_showsurfaces.integer;
4559 switch(vid.renderpath)
4561 case RENDERPATH_GL20:
4562 case RENDERPATH_D3D9:
4563 case RENDERPATH_D3D10:
4564 case RENDERPATH_D3D11:
4565 case RENDERPATH_GLES2:
4567 case RENDERPATH_GL13:
4568 case RENDERPATH_GL11:
4569 wanttangents = false;
4571 case RENDERPATH_SOFT:
4575 if (r_shownormals.integer)
4576 wanttangents = wantnormals = true;
4578 // TODO: thread this
4579 // NOTE: R_PrepareRTLights() also caches entities
4581 for (i = 0;i < r_refdef.scene.numentities;i++)
4582 if (r_refdef.viewcache.entityvisible[i])
4583 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4586 //==================================================================================
4588 static void R_View_UpdateEntityLighting (void)
4591 entity_render_t *ent;
4592 vec3_t tempdiffusenormal, avg;
4593 vec_t f, fa, fd, fdd;
4594 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4596 for (i = 0;i < r_refdef.scene.numentities;i++)
4598 ent = r_refdef.scene.entities[i];
4600 // skip unseen models
4601 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4605 if (ent->model && ent->model->brush.num_leafs)
4607 // TODO: use modellight for r_ambient settings on world?
4608 VectorSet(ent->modellight_ambient, 0, 0, 0);
4609 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4610 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4614 // fetch the lighting from the worldmodel data
4615 VectorClear(ent->modellight_ambient);
4616 VectorClear(ent->modellight_diffuse);
4617 VectorClear(tempdiffusenormal);
4618 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4621 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4623 // complete lightning for lit sprites
4624 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4625 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4627 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4628 org[2] = org[2] + r_overheadsprites_pushback.value;
4629 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4632 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4634 if(ent->flags & RENDER_EQUALIZE)
4636 // first fix up ambient lighting...
4637 if(r_equalize_entities_minambient.value > 0)
4639 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4642 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4643 if(fa < r_equalize_entities_minambient.value * fd)
4646 // fa'/fd' = minambient
4647 // fa'+0.25*fd' = fa+0.25*fd
4649 // fa' = fd' * minambient
4650 // fd'*(0.25+minambient) = fa+0.25*fd
4652 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4653 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4655 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4656 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4657 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4658 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4663 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4665 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4666 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4670 // adjust brightness and saturation to target
4671 avg[0] = avg[1] = avg[2] = fa / f;
4672 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4673 avg[0] = avg[1] = avg[2] = fd / f;
4674 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4680 VectorSet(ent->modellight_ambient, 1, 1, 1);
4682 // move the light direction into modelspace coordinates for lighting code
4683 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4684 if(VectorLength2(ent->modellight_lightdir) == 0)
4685 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4686 VectorNormalize(ent->modellight_lightdir);
4690 #define MAX_LINEOFSIGHTTRACES 64
4692 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4695 vec3_t boxmins, boxmaxs;
4698 dp_model_t *model = r_refdef.scene.worldmodel;
4700 if (!model || !model->brush.TraceLineOfSight)
4703 // expand the box a little
4704 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4705 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4706 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4707 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4708 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4709 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4711 // return true if eye is inside enlarged box
4712 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4716 VectorCopy(eye, start);
4717 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4718 if (model->brush.TraceLineOfSight(model, start, end))
4721 // try various random positions
4722 for (i = 0;i < numsamples;i++)
4724 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4725 if (model->brush.TraceLineOfSight(model, start, end))
4733 static void R_View_UpdateEntityVisible (void)
4738 entity_render_t *ent;
4740 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4741 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4742 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4743 : RENDER_EXTERIORMODEL;
4744 if (!r_drawviewmodel.integer)
4745 renderimask |= RENDER_VIEWMODEL;
4746 if (!r_drawexteriormodel.integer)
4747 renderimask |= RENDER_EXTERIORMODEL;
4748 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4750 // worldmodel can check visibility
4751 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4752 for (i = 0;i < r_refdef.scene.numentities;i++)
4754 ent = r_refdef.scene.entities[i];
4755 if (!(ent->flags & renderimask))
4756 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4757 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4758 r_refdef.viewcache.entityvisible[i] = true;
4760 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4761 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4763 for (i = 0;i < r_refdef.scene.numentities;i++)
4765 ent = r_refdef.scene.entities[i];
4766 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4768 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4770 continue; // temp entities do pvs only
4771 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4772 ent->last_trace_visibility = realtime;
4773 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4774 r_refdef.viewcache.entityvisible[i] = 0;
4781 // no worldmodel or it can't check visibility
4782 for (i = 0;i < r_refdef.scene.numentities;i++)
4784 ent = r_refdef.scene.entities[i];
4785 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4790 /// only used if skyrendermasked, and normally returns false
4791 int R_DrawBrushModelsSky (void)
4794 entity_render_t *ent;
4797 for (i = 0;i < r_refdef.scene.numentities;i++)
4799 if (!r_refdef.viewcache.entityvisible[i])
4801 ent = r_refdef.scene.entities[i];
4802 if (!ent->model || !ent->model->DrawSky)
4804 ent->model->DrawSky(ent);
4810 static void R_DrawNoModel(entity_render_t *ent);
4811 static void R_DrawModels(void)
4814 entity_render_t *ent;
4816 for (i = 0;i < r_refdef.scene.numentities;i++)
4818 if (!r_refdef.viewcache.entityvisible[i])
4820 ent = r_refdef.scene.entities[i];
4821 r_refdef.stats.entities++;
4822 if (ent->model && ent->model->Draw != NULL)
4823 ent->model->Draw(ent);
4829 static void R_DrawModelsDepth(void)
4832 entity_render_t *ent;
4834 for (i = 0;i < r_refdef.scene.numentities;i++)
4836 if (!r_refdef.viewcache.entityvisible[i])
4838 ent = r_refdef.scene.entities[i];
4839 if (ent->model && ent->model->DrawDepth != NULL)
4840 ent->model->DrawDepth(ent);
4844 static void R_DrawModelsDebug(void)
4847 entity_render_t *ent;
4849 for (i = 0;i < r_refdef.scene.numentities;i++)
4851 if (!r_refdef.viewcache.entityvisible[i])
4853 ent = r_refdef.scene.entities[i];
4854 if (ent->model && ent->model->DrawDebug != NULL)
4855 ent->model->DrawDebug(ent);
4859 static void R_DrawModelsAddWaterPlanes(void)
4862 entity_render_t *ent;
4864 for (i = 0;i < r_refdef.scene.numentities;i++)
4866 if (!r_refdef.viewcache.entityvisible[i])
4868 ent = r_refdef.scene.entities[i];
4869 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4870 ent->model->DrawAddWaterPlanes(ent);
4874 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4876 if (r_hdr_irisadaptation.integer)
4880 vec3_t diffusenormal;
4885 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4886 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4887 brightness = max(0.0000001f, brightness);
4888 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4889 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4890 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4891 current = r_hdr_irisadaptation_value.value;
4893 current = min(current + adjust, goal);
4894 else if (current > goal)
4895 current = max(current - adjust, goal);
4896 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4897 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4899 else if (r_hdr_irisadaptation_value.value != 1.0f)
4900 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4903 static void R_View_SetFrustum(const int *scissor)
4906 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4907 vec3_t forward, left, up, origin, v;
4911 // flipped x coordinates (because x points left here)
4912 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4913 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4915 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4916 switch(vid.renderpath)
4918 case RENDERPATH_D3D9:
4919 case RENDERPATH_D3D10:
4920 case RENDERPATH_D3D11:
4921 case RENDERPATH_SOFT:
4922 // non-flipped y coordinates
4923 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4924 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4926 case RENDERPATH_GL11:
4927 case RENDERPATH_GL13:
4928 case RENDERPATH_GL20:
4929 case RENDERPATH_GLES2:
4930 // non-flipped y coordinates
4931 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4932 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4937 // we can't trust r_refdef.view.forward and friends in reflected scenes
4938 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4941 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4942 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4943 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4944 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4945 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4946 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4947 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4948 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4949 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4950 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4951 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4952 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4956 zNear = r_refdef.nearclip;
4957 nudge = 1.0 - 1.0 / (1<<23);
4958 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4959 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4960 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4961 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4962 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4963 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4964 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4965 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4971 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4972 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4973 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4974 r_refdef.view.frustum[0].dist = m[15] - m[12];
4976 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4977 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4978 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4979 r_refdef.view.frustum[1].dist = m[15] + m[12];
4981 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4982 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4983 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4984 r_refdef.view.frustum[2].dist = m[15] - m[13];
4986 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4987 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4988 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4989 r_refdef.view.frustum[3].dist = m[15] + m[13];
4991 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4992 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4993 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4994 r_refdef.view.frustum[4].dist = m[15] - m[14];
4996 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4997 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4998 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4999 r_refdef.view.frustum[5].dist = m[15] + m[14];
5002 if (r_refdef.view.useperspective)
5004 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5005 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5006 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5007 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5008 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5010 // then the normals from the corners relative to origin
5011 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5012 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5013 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5014 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5016 // in a NORMAL view, forward cross left == up
5017 // in a REFLECTED view, forward cross left == down
5018 // so our cross products above need to be adjusted for a left handed coordinate system
5019 CrossProduct(forward, left, v);
5020 if(DotProduct(v, up) < 0)
5022 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5023 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5024 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5025 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5028 // Leaving those out was a mistake, those were in the old code, and they
5029 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5030 // I couldn't reproduce it after adding those normalizations. --blub
5031 VectorNormalize(r_refdef.view.frustum[0].normal);
5032 VectorNormalize(r_refdef.view.frustum[1].normal);
5033 VectorNormalize(r_refdef.view.frustum[2].normal);
5034 VectorNormalize(r_refdef.view.frustum[3].normal);
5036 // make the corners absolute
5037 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5038 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5039 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5040 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5043 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5045 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5046 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5047 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5048 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5049 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5053 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5054 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5055 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5056 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5057 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5058 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5059 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5060 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5061 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5062 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5064 r_refdef.view.numfrustumplanes = 5;
5066 if (r_refdef.view.useclipplane)
5068 r_refdef.view.numfrustumplanes = 6;
5069 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5072 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5073 PlaneClassify(r_refdef.view.frustum + i);
5075 // LordHavoc: note to all quake engine coders, Quake had a special case
5076 // for 90 degrees which assumed a square view (wrong), so I removed it,
5077 // Quake2 has it disabled as well.
5079 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5080 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5081 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5082 //PlaneClassify(&frustum[0]);
5084 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5085 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5086 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5087 //PlaneClassify(&frustum[1]);
5089 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5090 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5091 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5092 //PlaneClassify(&frustum[2]);
5094 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5095 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5096 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5097 //PlaneClassify(&frustum[3]);
5100 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5101 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5102 //PlaneClassify(&frustum[4]);
5105 void R_View_UpdateWithScissor(const int *myscissor)
5107 R_Main_ResizeViewCache();
5108 R_View_SetFrustum(myscissor);
5109 R_View_WorldVisibility(r_refdef.view.useclipplane);
5110 R_View_UpdateEntityVisible();
5111 R_View_UpdateEntityLighting();
5114 void R_View_Update(void)
5116 R_Main_ResizeViewCache();
5117 R_View_SetFrustum(NULL);
5118 R_View_WorldVisibility(r_refdef.view.useclipplane);
5119 R_View_UpdateEntityVisible();
5120 R_View_UpdateEntityLighting();
5123 void R_Mesh_SetMainRenderTargets(void)
5125 if (r_bloomstate.fbo_framebuffer)
5126 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5128 R_Mesh_ResetRenderTargets();
5131 void R_SetupView(qboolean allowwaterclippingplane)
5133 const float *customclipplane = NULL;
5135 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5137 // LordHavoc: couldn't figure out how to make this approach the
5138 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5139 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5140 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5141 dist = r_refdef.view.clipplane.dist;
5142 plane[0] = r_refdef.view.clipplane.normal[0];
5143 plane[1] = r_refdef.view.clipplane.normal[1];
5144 plane[2] = r_refdef.view.clipplane.normal[2];
5146 customclipplane = plane;
5149 if (!r_refdef.view.useperspective)
5150 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);
5151 else if (vid.stencil && r_useinfinitefarclip.integer)
5152 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);
5154 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);
5155 R_Mesh_SetMainRenderTargets();
5156 R_SetViewport(&r_refdef.view.viewport);
5159 void R_EntityMatrix(const matrix4x4_t *matrix)
5161 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5163 gl_modelmatrixchanged = false;
5164 gl_modelmatrix = *matrix;
5165 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5166 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5167 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5168 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5170 switch(vid.renderpath)
5172 case RENDERPATH_D3D9:
5174 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5175 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5178 case RENDERPATH_D3D10:
5179 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5181 case RENDERPATH_D3D11:
5182 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5184 case RENDERPATH_GL13:
5185 case RENDERPATH_GL11:
5186 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5188 case RENDERPATH_SOFT:
5189 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5190 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5192 case RENDERPATH_GL20:
5193 case RENDERPATH_GLES2:
5194 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5195 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5201 void R_ResetViewRendering2D(void)
5203 r_viewport_t viewport;
5206 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5207 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);
5208 R_Mesh_ResetRenderTargets();
5209 R_SetViewport(&viewport);
5210 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5211 GL_Color(1, 1, 1, 1);
5212 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5213 GL_BlendFunc(GL_ONE, GL_ZERO);
5214 GL_ScissorTest(false);
5215 GL_DepthMask(false);
5216 GL_DepthRange(0, 1);
5217 GL_DepthTest(false);
5218 GL_DepthFunc(GL_LEQUAL);
5219 R_EntityMatrix(&identitymatrix);
5220 R_Mesh_ResetTextureState();
5221 GL_PolygonOffset(0, 0);
5222 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5223 switch(vid.renderpath)
5225 case RENDERPATH_GL11:
5226 case RENDERPATH_GL13:
5227 case RENDERPATH_GL20:
5228 case RENDERPATH_GLES2:
5229 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5231 case RENDERPATH_D3D9:
5232 case RENDERPATH_D3D10:
5233 case RENDERPATH_D3D11:
5234 case RENDERPATH_SOFT:
5237 GL_CullFace(GL_NONE);
5240 void R_ResetViewRendering3D(void)
5245 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5246 GL_Color(1, 1, 1, 1);
5247 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5248 GL_BlendFunc(GL_ONE, GL_ZERO);
5249 GL_ScissorTest(true);
5251 GL_DepthRange(0, 1);
5253 GL_DepthFunc(GL_LEQUAL);
5254 R_EntityMatrix(&identitymatrix);
5255 R_Mesh_ResetTextureState();
5256 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5257 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5258 switch(vid.renderpath)
5260 case RENDERPATH_GL11:
5261 case RENDERPATH_GL13:
5262 case RENDERPATH_GL20:
5263 case RENDERPATH_GLES2:
5264 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5266 case RENDERPATH_D3D9:
5267 case RENDERPATH_D3D10:
5268 case RENDERPATH_D3D11:
5269 case RENDERPATH_SOFT:
5272 GL_CullFace(r_refdef.view.cullface_back);
5277 R_RenderView_UpdateViewVectors
5280 static void R_RenderView_UpdateViewVectors(void)
5282 // break apart the view matrix into vectors for various purposes
5283 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5284 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5285 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5286 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5287 // make an inverted copy of the view matrix for tracking sprites
5288 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5291 void R_RenderScene(void);
5292 void R_RenderWaterPlanes(void);
5294 static void R_Water_StartFrame(void)
5297 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5298 r_waterstate_waterplane_t *p;
5300 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5303 switch(vid.renderpath)
5305 case RENDERPATH_GL20:
5306 case RENDERPATH_D3D9:
5307 case RENDERPATH_D3D10:
5308 case RENDERPATH_D3D11:
5309 case RENDERPATH_SOFT:
5310 case RENDERPATH_GLES2:
5312 case RENDERPATH_GL13:
5313 case RENDERPATH_GL11:
5317 // set waterwidth and waterheight to the water resolution that will be
5318 // used (often less than the screen resolution for faster rendering)
5319 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5320 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5322 // calculate desired texture sizes
5323 // can't use water if the card does not support the texture size
5324 if (!r_water.integer || r_showsurfaces.integer)
5325 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5326 else if (vid.support.arb_texture_non_power_of_two)
5328 texturewidth = waterwidth;
5329 textureheight = waterheight;
5330 camerawidth = waterwidth;
5331 cameraheight = waterheight;
5335 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5336 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5337 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5338 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5341 // allocate textures as needed
5342 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5344 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5345 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5347 if (p->texture_refraction)
5348 R_FreeTexture(p->texture_refraction);
5349 p->texture_refraction = NULL;
5350 if (p->texture_reflection)
5351 R_FreeTexture(p->texture_reflection);
5352 p->texture_reflection = NULL;
5353 if (p->texture_camera)
5354 R_FreeTexture(p->texture_camera);
5355 p->texture_camera = NULL;
5357 memset(&r_waterstate, 0, sizeof(r_waterstate));
5358 r_waterstate.texturewidth = texturewidth;
5359 r_waterstate.textureheight = textureheight;
5360 r_waterstate.camerawidth = camerawidth;
5361 r_waterstate.cameraheight = cameraheight;
5364 if (r_waterstate.texturewidth)
5366 r_waterstate.enabled = true;
5368 // when doing a reduced render (HDR) we want to use a smaller area
5369 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5370 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5372 // set up variables that will be used in shader setup
5373 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5374 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5375 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5376 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5379 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5380 r_waterstate.numwaterplanes = 0;
5383 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5385 int triangleindex, planeindex;
5391 r_waterstate_waterplane_t *p;
5392 texture_t *t = R_GetCurrentTexture(surface->texture);
5394 // just use the first triangle with a valid normal for any decisions
5395 VectorClear(normal);
5396 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5398 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5399 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5400 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5401 TriangleNormal(vert[0], vert[1], vert[2], normal);
5402 if (VectorLength2(normal) >= 0.001)
5406 VectorCopy(normal, plane.normal);
5407 VectorNormalize(plane.normal);
5408 plane.dist = DotProduct(vert[0], plane.normal);
5409 PlaneClassify(&plane);
5410 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5412 // skip backfaces (except if nocullface is set)
5413 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5415 VectorNegate(plane.normal, plane.normal);
5417 PlaneClassify(&plane);
5421 // find a matching plane if there is one
5422 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5423 if(p->camera_entity == t->camera_entity)
5424 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5426 if (planeindex >= r_waterstate.maxwaterplanes)
5427 return; // nothing we can do, out of planes
5429 // if this triangle does not fit any known plane rendered this frame, add one
5430 if (planeindex >= r_waterstate.numwaterplanes)
5432 // store the new plane
5433 r_waterstate.numwaterplanes++;
5435 // clear materialflags and pvs
5436 p->materialflags = 0;
5437 p->pvsvalid = false;
5438 p->camera_entity = t->camera_entity;
5439 VectorCopy(surface->mins, p->mins);
5440 VectorCopy(surface->maxs, p->maxs);
5445 p->mins[0] = min(p->mins[0], surface->mins[0]);
5446 p->mins[1] = min(p->mins[1], surface->mins[1]);
5447 p->mins[2] = min(p->mins[2], surface->mins[2]);
5448 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5449 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5450 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5452 // merge this surface's materialflags into the waterplane
5453 p->materialflags |= t->currentmaterialflags;
5454 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5456 // merge this surface's PVS into the waterplane
5457 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5458 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5459 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5461 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5467 static void R_Water_ProcessPlanes(void)
5470 r_refdef_view_t originalview;
5471 r_refdef_view_t myview;
5473 r_waterstate_waterplane_t *p;
5476 originalview = r_refdef.view;
5478 // make sure enough textures are allocated
5479 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5481 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5483 if (!p->texture_refraction)
5484 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);
5485 if (!p->texture_refraction)
5488 else if (p->materialflags & MATERIALFLAG_CAMERA)
5490 if (!p->texture_camera)
5491 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);
5492 if (!p->texture_camera)
5496 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5498 if (!p->texture_reflection)
5499 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);
5500 if (!p->texture_reflection)
5506 r_refdef.view = originalview;
5507 r_refdef.view.showdebug = false;
5508 r_refdef.view.width = r_waterstate.waterwidth;
5509 r_refdef.view.height = r_waterstate.waterheight;
5510 r_refdef.view.useclipplane = true;
5511 myview = r_refdef.view;
5512 r_waterstate.renderingscene = true;
5513 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5515 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5517 r_refdef.view = myview;
5518 if(r_water_scissormode.integer)
5521 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5522 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5525 // render reflected scene and copy into texture
5526 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5527 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5528 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5529 r_refdef.view.clipplane = p->plane;
5531 // reverse the cullface settings for this render
5532 r_refdef.view.cullface_front = GL_FRONT;
5533 r_refdef.view.cullface_back = GL_BACK;
5534 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5536 r_refdef.view.usecustompvs = true;
5538 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5540 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5543 R_ResetViewRendering3D();
5544 R_ClearScreen(r_refdef.fogenabled);
5545 if(r_water_scissormode.integer & 2)
5546 R_View_UpdateWithScissor(myscissor);
5549 if(r_water_scissormode.integer & 1)
5550 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5553 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);
5556 // render the normal view scene and copy into texture
5557 // (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)
5558 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5560 r_refdef.view = myview;
5561 if(r_water_scissormode.integer)
5564 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5565 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5568 r_waterstate.renderingrefraction = true;
5570 r_refdef.view.clipplane = p->plane;
5571 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5572 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5574 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5576 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5577 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5578 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5579 R_RenderView_UpdateViewVectors();
5580 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5582 r_refdef.view.usecustompvs = true;
5583 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5587 PlaneClassify(&r_refdef.view.clipplane);
5589 R_ResetViewRendering3D();
5590 R_ClearScreen(r_refdef.fogenabled);
5591 if(r_water_scissormode.integer & 2)
5592 R_View_UpdateWithScissor(myscissor);
5595 if(r_water_scissormode.integer & 1)
5596 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5599 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);
5600 r_waterstate.renderingrefraction = false;
5602 else if (p->materialflags & MATERIALFLAG_CAMERA)
5604 r_refdef.view = myview;
5606 r_refdef.view.clipplane = p->plane;
5607 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5608 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5610 r_refdef.view.width = r_waterstate.camerawidth;
5611 r_refdef.view.height = r_waterstate.cameraheight;
5612 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5613 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5615 if(p->camera_entity)
5617 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5618 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5621 // note: all of the view is used for displaying... so
5622 // there is no use in scissoring
5624 // reverse the cullface settings for this render
5625 r_refdef.view.cullface_front = GL_FRONT;
5626 r_refdef.view.cullface_back = GL_BACK;
5627 // also reverse the view matrix
5628 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
5629 R_RenderView_UpdateViewVectors();
5630 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5632 r_refdef.view.usecustompvs = true;
5633 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);
5636 // camera needs no clipplane
5637 r_refdef.view.useclipplane = false;
5639 PlaneClassify(&r_refdef.view.clipplane);
5641 R_ResetViewRendering3D();
5642 R_ClearScreen(r_refdef.fogenabled);
5646 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);
5647 r_waterstate.renderingrefraction = false;
5651 r_waterstate.renderingscene = false;
5652 r_refdef.view = originalview;
5653 R_ResetViewRendering3D();
5654 R_ClearScreen(r_refdef.fogenabled);
5658 r_refdef.view = originalview;
5659 r_waterstate.renderingscene = false;
5660 Cvar_SetValueQuick(&r_water, 0);
5661 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5665 void R_Bloom_StartFrame(void)
5667 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5670 switch(vid.renderpath)
5672 case RENDERPATH_GL20:
5673 case RENDERPATH_D3D9:
5674 case RENDERPATH_D3D10:
5675 case RENDERPATH_D3D11:
5676 case RENDERPATH_SOFT:
5677 case RENDERPATH_GLES2:
5679 case RENDERPATH_GL13:
5680 case RENDERPATH_GL11:
5684 // set bloomwidth and bloomheight to the bloom resolution that will be
5685 // used (often less than the screen resolution for faster rendering)
5686 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5687 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5688 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5689 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5690 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5692 // calculate desired texture sizes
5693 if (vid.support.arb_texture_non_power_of_two)
5695 screentexturewidth = r_refdef.view.width;
5696 screentextureheight = r_refdef.view.height;
5697 bloomtexturewidth = r_bloomstate.bloomwidth;
5698 bloomtextureheight = r_bloomstate.bloomheight;
5702 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5703 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5704 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5705 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5708 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))
5710 Cvar_SetValueQuick(&r_hdr, 0);
5711 Cvar_SetValueQuick(&r_bloom, 0);
5712 Cvar_SetValueQuick(&r_motionblur, 0);
5713 Cvar_SetValueQuick(&r_damageblur, 0);
5716 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)
5717 screentexturewidth = screentextureheight = 0;
5718 if (!r_hdr.integer && !r_bloom.integer)
5719 bloomtexturewidth = bloomtextureheight = 0;
5721 textype = TEXTYPE_COLORBUFFER;
5722 switch (vid.renderpath)
5724 case RENDERPATH_GL20:
5725 case RENDERPATH_GLES2:
5726 if (vid.support.ext_framebuffer_object)
5728 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5729 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5732 case RENDERPATH_D3D9:
5733 case RENDERPATH_D3D10:
5734 case RENDERPATH_D3D11:
5735 case RENDERPATH_SOFT:
5736 case RENDERPATH_GL13:
5737 case RENDERPATH_GL11:
5741 // allocate textures as needed
5742 if (r_bloomstate.screentexturewidth != screentexturewidth
5743 || r_bloomstate.screentextureheight != screentextureheight
5744 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5745 || r_bloomstate.bloomtextureheight != bloomtextureheight
5746 || r_bloomstate.texturetype != textype
5747 || r_bloomstate.viewfbo != r_viewfbo.integer)
5749 if (r_bloomstate.texture_bloom)
5750 R_FreeTexture(r_bloomstate.texture_bloom);
5751 r_bloomstate.texture_bloom = NULL;
5752 if (r_bloomstate.texture_screen)
5753 R_FreeTexture(r_bloomstate.texture_screen);
5754 r_bloomstate.texture_screen = NULL;
5755 if (r_bloomstate.fbo_framebuffer)
5756 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5757 r_bloomstate.fbo_framebuffer = 0;
5758 if (r_bloomstate.texture_framebuffercolor)
5759 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5760 r_bloomstate.texture_framebuffercolor = NULL;
5761 if (r_bloomstate.texture_framebufferdepth)
5762 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5763 r_bloomstate.texture_framebufferdepth = NULL;
5764 r_bloomstate.screentexturewidth = screentexturewidth;
5765 r_bloomstate.screentextureheight = screentextureheight;
5766 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5767 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);
5768 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5770 // FIXME: choose depth bits based on a cvar
5771 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5772 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);
5773 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5774 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5775 // render depth into one texture and normalmap into the other
5779 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5780 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5781 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5782 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5783 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5786 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5787 r_bloomstate.bloomtextureheight = bloomtextureheight;
5788 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5789 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);
5790 r_bloomstate.viewfbo = r_viewfbo.integer;
5791 r_bloomstate.texturetype = textype;
5794 // when doing a reduced render (HDR) we want to use a smaller area
5795 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5796 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5797 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5798 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5799 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5801 // set up a texcoord array for the full resolution screen image
5802 // (we have to keep this around to copy back during final render)
5803 r_bloomstate.screentexcoord2f[0] = 0;
5804 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5805 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5806 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5807 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5808 r_bloomstate.screentexcoord2f[5] = 0;
5809 r_bloomstate.screentexcoord2f[6] = 0;
5810 r_bloomstate.screentexcoord2f[7] = 0;
5812 // set up a texcoord array for the reduced resolution bloom image
5813 // (which will be additive blended over the screen image)
5814 r_bloomstate.bloomtexcoord2f[0] = 0;
5815 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5816 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5817 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5818 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5819 r_bloomstate.bloomtexcoord2f[5] = 0;
5820 r_bloomstate.bloomtexcoord2f[6] = 0;
5821 r_bloomstate.bloomtexcoord2f[7] = 0;
5823 switch(vid.renderpath)
5825 case RENDERPATH_GL11:
5826 case RENDERPATH_GL13:
5827 case RENDERPATH_GL20:
5828 case RENDERPATH_SOFT:
5829 case RENDERPATH_GLES2:
5831 case RENDERPATH_D3D9:
5832 case RENDERPATH_D3D10:
5833 case RENDERPATH_D3D11:
5836 for (i = 0;i < 4;i++)
5838 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5839 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5840 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5841 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5847 if (r_hdr.integer || r_bloom.integer)
5849 r_bloomstate.enabled = true;
5850 r_bloomstate.hdr = r_hdr.integer != 0;
5853 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);
5855 if (r_bloomstate.fbo_framebuffer)
5856 r_refdef.view.clear = true;
5859 void R_Bloom_CopyBloomTexture(float colorscale)
5861 r_refdef.stats.bloom++;
5863 // scale down screen texture to the bloom texture size
5865 R_Mesh_SetMainRenderTargets();
5866 R_SetViewport(&r_bloomstate.viewport);
5867 GL_BlendFunc(GL_ONE, GL_ZERO);
5868 GL_Color(colorscale, colorscale, colorscale, 1);
5869 // 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...
5870 switch(vid.renderpath)
5872 case RENDERPATH_GL11:
5873 case RENDERPATH_GL13:
5874 case RENDERPATH_GL20:
5875 case RENDERPATH_SOFT:
5876 case RENDERPATH_GLES2:
5877 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5879 case RENDERPATH_D3D9:
5880 case RENDERPATH_D3D10:
5881 case RENDERPATH_D3D11:
5882 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5885 // TODO: do boxfilter scale-down in shader?
5886 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5887 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5888 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5890 // we now have a bloom image in the framebuffer
5891 // copy it into the bloom image texture for later processing
5892 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);
5893 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5896 void R_Bloom_CopyHDRTexture(void)
5898 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);
5899 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5902 void R_Bloom_MakeTexture(void)
5905 float xoffset, yoffset, r, brighten;
5907 r_refdef.stats.bloom++;
5909 R_ResetViewRendering2D();
5911 // we have a bloom image in the framebuffer
5913 R_SetViewport(&r_bloomstate.viewport);
5915 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5918 r = bound(0, r_bloom_colorexponent.value / x, 1);
5919 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5921 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5922 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5923 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5924 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5926 // copy the vertically blurred bloom view to a texture
5927 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);
5928 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5931 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5932 brighten = r_bloom_brighten.value;
5934 brighten *= r_hdr_range.value;
5935 brighten = sqrt(brighten);
5937 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5938 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5940 for (dir = 0;dir < 2;dir++)
5942 // blend on at multiple vertical offsets to achieve a vertical blur
5943 // TODO: do offset blends using GLSL
5944 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5945 GL_BlendFunc(GL_ONE, GL_ZERO);
5946 for (x = -range;x <= range;x++)
5948 if (!dir){xoffset = 0;yoffset = x;}
5949 else {xoffset = x;yoffset = 0;}
5950 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5951 yoffset /= (float)r_bloomstate.bloomtextureheight;
5952 // compute a texcoord array with the specified x and y offset
5953 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5954 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5955 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5956 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5957 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5958 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5959 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5960 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5961 // this r value looks like a 'dot' particle, fading sharply to
5962 // black at the edges
5963 // (probably not realistic but looks good enough)
5964 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5965 //r = brighten/(range*2+1);
5966 r = brighten / (range * 2 + 1);
5968 r *= (1 - x*x/(float)(range*range));
5969 GL_Color(r, r, r, 1);
5970 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5971 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5972 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5973 GL_BlendFunc(GL_ONE, GL_ONE);
5976 // copy the vertically blurred bloom view to a texture
5977 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);
5978 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5982 void R_HDR_RenderBloomTexture(void)
5984 int oldwidth, oldheight;
5985 float oldcolorscale;
5986 qboolean oldwaterstate;
5988 oldwaterstate = r_waterstate.enabled;
5989 oldcolorscale = r_refdef.view.colorscale;
5990 oldwidth = r_refdef.view.width;
5991 oldheight = r_refdef.view.height;
5992 r_refdef.view.width = r_bloomstate.bloomwidth;
5993 r_refdef.view.height = r_bloomstate.bloomheight;
5995 if(r_hdr.integer < 2)
5996 r_waterstate.enabled = false;
5998 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5999 // TODO: add exposure compensation features
6000 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6002 r_refdef.view.showdebug = false;
6003 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6005 R_ResetViewRendering3D();
6007 R_ClearScreen(r_refdef.fogenabled);
6008 if (r_timereport_active)
6009 R_TimeReport("HDRclear");
6012 if (r_timereport_active)
6013 R_TimeReport("visibility");
6015 // only do secondary renders with HDR if r_hdr is 2 or higher
6016 r_waterstate.numwaterplanes = 0;
6017 if (r_waterstate.enabled)
6018 R_RenderWaterPlanes();
6020 r_refdef.view.showdebug = true;
6022 r_waterstate.numwaterplanes = 0;
6024 R_ResetViewRendering2D();
6026 R_Bloom_CopyHDRTexture();
6027 R_Bloom_MakeTexture();
6029 // restore the view settings
6030 r_waterstate.enabled = oldwaterstate;
6031 r_refdef.view.width = oldwidth;
6032 r_refdef.view.height = oldheight;
6033 r_refdef.view.colorscale = oldcolorscale;
6035 R_ResetViewRendering3D();
6037 R_ClearScreen(r_refdef.fogenabled);
6038 if (r_timereport_active)
6039 R_TimeReport("viewclear");
6042 static void R_BlendView(void)
6044 unsigned int permutation;
6045 float uservecs[4][4];
6047 switch (vid.renderpath)
6049 case RENDERPATH_GL20:
6050 case RENDERPATH_D3D9:
6051 case RENDERPATH_D3D10:
6052 case RENDERPATH_D3D11:
6053 case RENDERPATH_SOFT:
6054 case RENDERPATH_GLES2:
6056 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6057 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6058 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6059 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6060 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6062 if (r_bloomstate.texture_screen)
6064 // make sure the buffer is available
6065 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6067 R_ResetViewRendering2D();
6068 R_Mesh_SetMainRenderTargets();
6070 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6072 // declare variables
6074 static float avgspeed;
6076 speed = VectorLength(cl.movement_velocity);
6078 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6079 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6081 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6082 speed = bound(0, speed, 1);
6083 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6085 // calculate values into a standard alpha
6086 cl.motionbluralpha = 1 - exp(-
6088 (r_motionblur.value * speed / 80)
6090 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6093 max(0.0001, cl.time - cl.oldtime) // fps independent
6096 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6097 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6099 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6101 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6102 GL_Color(1, 1, 1, cl.motionbluralpha);
6103 switch(vid.renderpath)
6105 case RENDERPATH_GL11:
6106 case RENDERPATH_GL13:
6107 case RENDERPATH_GL20:
6108 case RENDERPATH_SOFT:
6109 case RENDERPATH_GLES2:
6110 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6112 case RENDERPATH_D3D9:
6113 case RENDERPATH_D3D10:
6114 case RENDERPATH_D3D11:
6115 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6118 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6119 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6120 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6124 // copy view into the screen texture
6125 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);
6126 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6128 else if (!r_bloomstate.texture_bloom)
6130 // we may still have to do view tint...
6131 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6133 // apply a color tint to the whole view
6134 R_ResetViewRendering2D();
6135 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6136 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6137 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6139 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6141 break; // no screen processing, no bloom, skip it
6144 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6146 // render simple bloom effect
6147 // copy the screen and shrink it and darken it for the bloom process
6148 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6149 // make the bloom texture
6150 R_Bloom_MakeTexture();
6153 #if _MSC_VER >= 1400
6154 #define sscanf sscanf_s
6156 memset(uservecs, 0, sizeof(uservecs));
6157 if (r_glsl_postprocess_uservec1_enable.integer)
6158 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6159 if (r_glsl_postprocess_uservec2_enable.integer)
6160 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6161 if (r_glsl_postprocess_uservec3_enable.integer)
6162 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6163 if (r_glsl_postprocess_uservec4_enable.integer)
6164 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6166 R_ResetViewRendering2D();
6167 GL_Color(1, 1, 1, 1);
6168 GL_BlendFunc(GL_ONE, GL_ZERO);
6170 switch(vid.renderpath)
6172 case RENDERPATH_GL20:
6173 case RENDERPATH_GLES2:
6174 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6175 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6176 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6177 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6178 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6179 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]);
6180 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6181 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]);
6182 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]);
6183 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]);
6184 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]);
6185 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6186 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6187 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);
6189 case RENDERPATH_D3D9:
6191 // 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...
6192 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6193 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6194 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6195 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6196 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6197 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6198 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6199 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6200 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6201 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6202 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6203 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6204 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6205 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6208 case RENDERPATH_D3D10:
6209 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6211 case RENDERPATH_D3D11:
6212 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6214 case RENDERPATH_SOFT:
6215 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6216 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6217 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6218 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6219 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6220 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6221 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6222 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6223 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6224 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6225 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6226 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6227 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6228 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6233 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6234 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6236 case RENDERPATH_GL13:
6237 case RENDERPATH_GL11:
6238 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6240 // apply a color tint to the whole view
6241 R_ResetViewRendering2D();
6242 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6243 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6244 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6245 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6246 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6252 matrix4x4_t r_waterscrollmatrix;
6254 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6256 if (r_refdef.fog_density)
6258 r_refdef.fogcolor[0] = r_refdef.fog_red;
6259 r_refdef.fogcolor[1] = r_refdef.fog_green;
6260 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6262 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6263 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6264 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6265 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6269 VectorCopy(r_refdef.fogcolor, fogvec);
6270 // color.rgb *= ContrastBoost * SceneBrightness;
6271 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6272 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6273 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6274 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6279 void R_UpdateVariables(void)
6283 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6285 r_refdef.farclip = r_farclip_base.value;
6286 if (r_refdef.scene.worldmodel)
6287 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6288 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6290 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6291 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6292 r_refdef.polygonfactor = 0;
6293 r_refdef.polygonoffset = 0;
6294 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6295 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6297 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6298 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6299 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6300 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6301 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6302 if (FAKELIGHT_ENABLED)
6304 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6306 if (r_showsurfaces.integer)
6308 r_refdef.scene.rtworld = false;
6309 r_refdef.scene.rtworldshadows = false;
6310 r_refdef.scene.rtdlight = false;
6311 r_refdef.scene.rtdlightshadows = false;
6312 r_refdef.lightmapintensity = 0;
6315 if (gamemode == GAME_NEHAHRA)
6317 if (gl_fogenable.integer)
6319 r_refdef.oldgl_fogenable = true;
6320 r_refdef.fog_density = gl_fogdensity.value;
6321 r_refdef.fog_red = gl_fogred.value;
6322 r_refdef.fog_green = gl_foggreen.value;
6323 r_refdef.fog_blue = gl_fogblue.value;
6324 r_refdef.fog_alpha = 1;
6325 r_refdef.fog_start = 0;
6326 r_refdef.fog_end = gl_skyclip.value;
6327 r_refdef.fog_height = 1<<30;
6328 r_refdef.fog_fadedepth = 128;
6330 else if (r_refdef.oldgl_fogenable)
6332 r_refdef.oldgl_fogenable = false;
6333 r_refdef.fog_density = 0;
6334 r_refdef.fog_red = 0;
6335 r_refdef.fog_green = 0;
6336 r_refdef.fog_blue = 0;
6337 r_refdef.fog_alpha = 0;
6338 r_refdef.fog_start = 0;
6339 r_refdef.fog_end = 0;
6340 r_refdef.fog_height = 1<<30;
6341 r_refdef.fog_fadedepth = 128;
6345 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6346 r_refdef.fog_start = max(0, r_refdef.fog_start);
6347 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6349 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6351 if (r_refdef.fog_density && r_drawfog.integer)
6353 r_refdef.fogenabled = true;
6354 // this is the point where the fog reaches 0.9986 alpha, which we
6355 // consider a good enough cutoff point for the texture
6356 // (0.9986 * 256 == 255.6)
6357 if (r_fog_exp2.integer)
6358 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6360 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6361 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6362 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6363 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6364 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6365 R_BuildFogHeightTexture();
6366 // fog color was already set
6367 // update the fog texture
6368 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)
6369 R_BuildFogTexture();
6370 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6371 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6374 r_refdef.fogenabled = false;
6376 switch(vid.renderpath)
6378 case RENDERPATH_GL20:
6379 case RENDERPATH_D3D9:
6380 case RENDERPATH_D3D10:
6381 case RENDERPATH_D3D11:
6382 case RENDERPATH_SOFT:
6383 case RENDERPATH_GLES2:
6384 if(v_glslgamma.integer && !vid_gammatables_trivial)
6386 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6388 // build GLSL gamma texture
6389 #define RAMPWIDTH 256
6390 unsigned short ramp[RAMPWIDTH * 3];
6391 unsigned char rampbgr[RAMPWIDTH][4];
6394 r_texture_gammaramps_serial = vid_gammatables_serial;
6396 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6397 for(i = 0; i < RAMPWIDTH; ++i)
6399 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6400 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6401 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6404 if (r_texture_gammaramps)
6406 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6410 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6416 // remove GLSL gamma texture
6419 case RENDERPATH_GL13:
6420 case RENDERPATH_GL11:
6425 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6426 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6432 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6433 if( scenetype != r_currentscenetype ) {
6434 // store the old scenetype
6435 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6436 r_currentscenetype = scenetype;
6437 // move in the new scene
6438 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6447 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6449 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6450 if( scenetype == r_currentscenetype ) {
6451 return &r_refdef.scene;
6453 return &r_scenes_store[ scenetype ];
6462 int dpsoftrast_test;
6463 void R_RenderView(void)
6465 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6467 dpsoftrast_test = r_test.integer;
6469 if (r_timereport_active)
6470 R_TimeReport("start");
6471 r_textureframe++; // used only by R_GetCurrentTexture
6472 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6474 if(R_CompileShader_CheckStaticParms())
6477 if (!r_drawentities.integer)
6478 r_refdef.scene.numentities = 0;
6480 R_AnimCache_ClearCache();
6481 R_FrameData_NewFrame();
6483 /* adjust for stereo display */
6484 if(R_Stereo_Active())
6486 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);
6487 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6490 if (r_refdef.view.isoverlay)
6492 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6493 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6494 R_TimeReport("depthclear");
6496 r_refdef.view.showdebug = false;
6498 r_waterstate.enabled = false;
6499 r_waterstate.numwaterplanes = 0;
6503 r_refdef.view.matrix = originalmatrix;
6509 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6511 r_refdef.view.matrix = originalmatrix;
6512 return; //Host_Error ("R_RenderView: NULL worldmodel");
6515 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6517 R_RenderView_UpdateViewVectors();
6519 R_Shadow_UpdateWorldLightSelection();
6521 R_Bloom_StartFrame();
6522 R_Water_StartFrame();
6525 if (r_timereport_active)
6526 R_TimeReport("viewsetup");
6528 R_ResetViewRendering3D();
6530 if (r_refdef.view.clear || r_refdef.fogenabled)
6532 R_ClearScreen(r_refdef.fogenabled);
6533 if (r_timereport_active)
6534 R_TimeReport("viewclear");
6536 r_refdef.view.clear = true;
6538 // this produces a bloom texture to be used in R_BlendView() later
6539 if (r_hdr.integer && r_bloomstate.bloomwidth)
6541 R_HDR_RenderBloomTexture();
6542 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6543 r_textureframe++; // used only by R_GetCurrentTexture
6546 r_refdef.view.showdebug = true;
6549 if (r_timereport_active)
6550 R_TimeReport("visibility");
6552 r_waterstate.numwaterplanes = 0;
6553 if (r_waterstate.enabled)
6554 R_RenderWaterPlanes();
6557 r_waterstate.numwaterplanes = 0;
6560 if (r_timereport_active)
6561 R_TimeReport("blendview");
6563 GL_Scissor(0, 0, vid.width, vid.height);
6564 GL_ScissorTest(false);
6566 r_refdef.view.matrix = originalmatrix;
6571 void R_RenderWaterPlanes(void)
6573 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6575 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6576 if (r_timereport_active)
6577 R_TimeReport("waterworld");
6580 // don't let sound skip if going slow
6581 if (r_refdef.scene.extraupdate)
6584 R_DrawModelsAddWaterPlanes();
6585 if (r_timereport_active)
6586 R_TimeReport("watermodels");
6588 if (r_waterstate.numwaterplanes)
6590 R_Water_ProcessPlanes();
6591 if (r_timereport_active)
6592 R_TimeReport("waterscenes");
6596 extern void R_DrawLightningBeams (void);
6597 extern void VM_CL_AddPolygonsToMeshQueue (void);
6598 extern void R_DrawPortals (void);
6599 extern cvar_t cl_locs_show;
6600 static void R_DrawLocs(void);
6601 static void R_DrawEntityBBoxes(void);
6602 static void R_DrawModelDecals(void);
6603 extern void R_DrawModelShadows(void);
6604 extern void R_DrawModelShadowMaps(void);
6605 extern cvar_t cl_decals_newsystem;
6606 extern qboolean r_shadow_usingdeferredprepass;
6607 void R_RenderScene(void)
6609 qboolean shadowmapping = false;
6611 if (r_timereport_active)
6612 R_TimeReport("beginscene");
6614 r_refdef.stats.renders++;
6618 // don't let sound skip if going slow
6619 if (r_refdef.scene.extraupdate)
6622 R_MeshQueue_BeginScene();
6626 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);
6628 if (r_timereport_active)
6629 R_TimeReport("skystartframe");
6631 if (cl.csqc_vidvars.drawworld)
6633 // don't let sound skip if going slow
6634 if (r_refdef.scene.extraupdate)
6637 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6639 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6640 if (r_timereport_active)
6641 R_TimeReport("worldsky");
6644 if (R_DrawBrushModelsSky() && r_timereport_active)
6645 R_TimeReport("bmodelsky");
6647 if (skyrendermasked && skyrenderlater)
6649 // we have to force off the water clipping plane while rendering sky
6653 if (r_timereport_active)
6654 R_TimeReport("sky");
6658 R_AnimCache_CacheVisibleEntities();
6659 if (r_timereport_active)
6660 R_TimeReport("animation");
6662 R_Shadow_PrepareLights();
6663 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6664 R_Shadow_PrepareModelShadows();
6665 if (r_timereport_active)
6666 R_TimeReport("preparelights");
6668 if (R_Shadow_ShadowMappingEnabled())
6669 shadowmapping = true;
6671 if (r_shadow_usingdeferredprepass)
6672 R_Shadow_DrawPrepass();
6674 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6676 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6677 if (r_timereport_active)
6678 R_TimeReport("worlddepth");
6680 if (r_depthfirst.integer >= 2)
6682 R_DrawModelsDepth();
6683 if (r_timereport_active)
6684 R_TimeReport("modeldepth");
6687 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6689 R_DrawModelShadowMaps();
6690 R_ResetViewRendering3D();
6691 // don't let sound skip if going slow
6692 if (r_refdef.scene.extraupdate)
6696 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6698 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6699 if (r_timereport_active)
6700 R_TimeReport("world");
6703 // don't let sound skip if going slow
6704 if (r_refdef.scene.extraupdate)
6708 if (r_timereport_active)
6709 R_TimeReport("models");
6711 // don't let sound skip if going slow
6712 if (r_refdef.scene.extraupdate)
6715 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6717 R_DrawModelShadows();
6718 R_ResetViewRendering3D();
6719 // don't let sound skip if going slow
6720 if (r_refdef.scene.extraupdate)
6724 if (!r_shadow_usingdeferredprepass)
6726 R_Shadow_DrawLights();
6727 if (r_timereport_active)
6728 R_TimeReport("rtlights");
6731 // don't let sound skip if going slow
6732 if (r_refdef.scene.extraupdate)
6735 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6737 R_DrawModelShadows();
6738 R_ResetViewRendering3D();
6739 // don't let sound skip if going slow
6740 if (r_refdef.scene.extraupdate)
6744 if (cl.csqc_vidvars.drawworld)
6746 if (cl_decals_newsystem.integer)
6748 R_DrawModelDecals();
6749 if (r_timereport_active)
6750 R_TimeReport("modeldecals");
6755 if (r_timereport_active)
6756 R_TimeReport("decals");
6760 if (r_timereport_active)
6761 R_TimeReport("particles");
6764 if (r_timereport_active)
6765 R_TimeReport("explosions");
6767 R_DrawLightningBeams();
6768 if (r_timereport_active)
6769 R_TimeReport("lightning");
6772 VM_CL_AddPolygonsToMeshQueue();
6774 if (r_refdef.view.showdebug)
6776 if (cl_locs_show.integer)
6779 if (r_timereport_active)
6780 R_TimeReport("showlocs");
6783 if (r_drawportals.integer)
6786 if (r_timereport_active)
6787 R_TimeReport("portals");
6790 if (r_showbboxes.value > 0)
6792 R_DrawEntityBBoxes();
6793 if (r_timereport_active)
6794 R_TimeReport("bboxes");
6798 R_MeshQueue_RenderTransparent();
6799 if (r_timereport_active)
6800 R_TimeReport("drawtrans");
6802 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))
6804 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6805 if (r_timereport_active)
6806 R_TimeReport("worlddebug");
6807 R_DrawModelsDebug();
6808 if (r_timereport_active)
6809 R_TimeReport("modeldebug");
6812 if (cl.csqc_vidvars.drawworld)
6814 R_Shadow_DrawCoronas();
6815 if (r_timereport_active)
6816 R_TimeReport("coronas");
6821 GL_DepthTest(false);
6822 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6823 GL_Color(1, 1, 1, 1);
6824 qglBegin(GL_POLYGON);
6825 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6826 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6827 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6828 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6830 qglBegin(GL_POLYGON);
6831 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]);
6832 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]);
6833 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]);
6834 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]);
6836 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6840 // don't let sound skip if going slow
6841 if (r_refdef.scene.extraupdate)
6844 R_ResetViewRendering2D();
6847 static const unsigned short bboxelements[36] =
6857 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6860 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6862 RSurf_ActiveWorldEntity();
6864 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6865 GL_DepthMask(false);
6866 GL_DepthRange(0, 1);
6867 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6868 // R_Mesh_ResetTextureState();
6870 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6871 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6872 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6873 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6874 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6875 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6876 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6877 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6878 R_FillColors(color4f, 8, cr, cg, cb, ca);
6879 if (r_refdef.fogenabled)
6881 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6883 f1 = RSurf_FogVertex(v);
6885 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6886 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6887 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6890 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6891 R_Mesh_ResetTextureState();
6892 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6893 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6896 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6900 prvm_edict_t *edict;
6901 prvm_prog_t *prog_save = prog;
6903 // this function draws bounding boxes of server entities
6907 GL_CullFace(GL_NONE);
6908 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6912 for (i = 0;i < numsurfaces;i++)
6914 edict = PRVM_EDICT_NUM(surfacelist[i]);
6915 switch ((int)edict->fields.server->solid)
6917 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6918 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6919 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6920 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6921 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6922 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6924 color[3] *= r_showbboxes.value;
6925 color[3] = bound(0, color[3], 1);
6926 GL_DepthTest(!r_showdisabledepthtest.integer);
6927 GL_CullFace(r_refdef.view.cullface_front);
6928 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6934 static void R_DrawEntityBBoxes(void)
6937 prvm_edict_t *edict;
6939 prvm_prog_t *prog_save = prog;
6941 // this function draws bounding boxes of server entities
6947 for (i = 0;i < prog->num_edicts;i++)
6949 edict = PRVM_EDICT_NUM(i);
6950 if (edict->priv.server->free)
6952 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6953 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6955 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6957 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6958 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6964 static const int nomodelelement3i[24] =
6976 static const unsigned short nomodelelement3s[24] =
6988 static const float nomodelvertex3f[6*3] =
6998 static const float nomodelcolor4f[6*4] =
7000 0.0f, 0.0f, 0.5f, 1.0f,
7001 0.0f, 0.0f, 0.5f, 1.0f,
7002 0.0f, 0.5f, 0.0f, 1.0f,
7003 0.0f, 0.5f, 0.0f, 1.0f,
7004 0.5f, 0.0f, 0.0f, 1.0f,
7005 0.5f, 0.0f, 0.0f, 1.0f
7008 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7014 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);
7016 // this is only called once per entity so numsurfaces is always 1, and
7017 // surfacelist is always {0}, so this code does not handle batches
7019 if (rsurface.ent_flags & RENDER_ADDITIVE)
7021 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7022 GL_DepthMask(false);
7024 else if (rsurface.colormod[3] < 1)
7026 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7027 GL_DepthMask(false);
7031 GL_BlendFunc(GL_ONE, GL_ZERO);
7034 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7035 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7036 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7037 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7038 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7039 for (i = 0, c = color4f;i < 6;i++, c += 4)
7041 c[0] *= rsurface.colormod[0];
7042 c[1] *= rsurface.colormod[1];
7043 c[2] *= rsurface.colormod[2];
7044 c[3] *= rsurface.colormod[3];
7046 if (r_refdef.fogenabled)
7048 for (i = 0, c = color4f;i < 6;i++, c += 4)
7050 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7052 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7053 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7054 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7057 // R_Mesh_ResetTextureState();
7058 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7059 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7060 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7063 void R_DrawNoModel(entity_render_t *ent)
7066 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7067 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7068 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7070 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7073 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7075 vec3_t right1, right2, diff, normal;
7077 VectorSubtract (org2, org1, normal);
7079 // calculate 'right' vector for start
7080 VectorSubtract (r_refdef.view.origin, org1, diff);
7081 CrossProduct (normal, diff, right1);
7082 VectorNormalize (right1);
7084 // calculate 'right' vector for end
7085 VectorSubtract (r_refdef.view.origin, org2, diff);
7086 CrossProduct (normal, diff, right2);
7087 VectorNormalize (right2);
7089 vert[ 0] = org1[0] + width * right1[0];
7090 vert[ 1] = org1[1] + width * right1[1];
7091 vert[ 2] = org1[2] + width * right1[2];
7092 vert[ 3] = org1[0] - width * right1[0];
7093 vert[ 4] = org1[1] - width * right1[1];
7094 vert[ 5] = org1[2] - width * right1[2];
7095 vert[ 6] = org2[0] - width * right2[0];
7096 vert[ 7] = org2[1] - width * right2[1];
7097 vert[ 8] = org2[2] - width * right2[2];
7098 vert[ 9] = org2[0] + width * right2[0];
7099 vert[10] = org2[1] + width * right2[1];
7100 vert[11] = org2[2] + width * right2[2];
7103 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)
7105 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7106 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7107 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7108 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7109 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7110 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7111 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7112 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7113 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7114 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7115 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7116 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7119 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7124 VectorSet(v, x, y, z);
7125 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7126 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7128 if (i == mesh->numvertices)
7130 if (mesh->numvertices < mesh->maxvertices)
7132 VectorCopy(v, vertex3f);
7133 mesh->numvertices++;
7135 return mesh->numvertices;
7141 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7145 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7146 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7147 e = mesh->element3i + mesh->numtriangles * 3;
7148 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7150 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7151 if (mesh->numtriangles < mesh->maxtriangles)
7156 mesh->numtriangles++;
7158 element[1] = element[2];
7162 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7166 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7167 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7168 e = mesh->element3i + mesh->numtriangles * 3;
7169 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7171 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7172 if (mesh->numtriangles < mesh->maxtriangles)
7177 mesh->numtriangles++;
7179 element[1] = element[2];
7183 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7184 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7186 int planenum, planenum2;
7189 mplane_t *plane, *plane2;
7191 double temppoints[2][256*3];
7192 // figure out how large a bounding box we need to properly compute this brush
7194 for (w = 0;w < numplanes;w++)
7195 maxdist = max(maxdist, fabs(planes[w].dist));
7196 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7197 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7198 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7202 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7203 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7205 if (planenum2 == planenum)
7207 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);
7210 if (tempnumpoints < 3)
7212 // generate elements forming a triangle fan for this polygon
7213 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7217 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)
7219 texturelayer_t *layer;
7220 layer = t->currentlayers + t->currentnumlayers++;
7222 layer->depthmask = depthmask;
7223 layer->blendfunc1 = blendfunc1;
7224 layer->blendfunc2 = blendfunc2;
7225 layer->texture = texture;
7226 layer->texmatrix = *matrix;
7227 layer->color[0] = r;
7228 layer->color[1] = g;
7229 layer->color[2] = b;
7230 layer->color[3] = a;
7233 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7235 if(parms[0] == 0 && parms[1] == 0)
7237 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7238 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7243 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7246 index = parms[2] + r_refdef.scene.time * parms[3];
7247 index -= floor(index);
7248 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7251 case Q3WAVEFUNC_NONE:
7252 case Q3WAVEFUNC_NOISE:
7253 case Q3WAVEFUNC_COUNT:
7256 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7257 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7258 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7259 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7260 case Q3WAVEFUNC_TRIANGLE:
7262 f = index - floor(index);
7273 f = parms[0] + parms[1] * f;
7274 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7275 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7279 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7284 matrix4x4_t matrix, temp;
7285 switch(tcmod->tcmod)
7289 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7290 matrix = r_waterscrollmatrix;
7292 matrix = identitymatrix;
7294 case Q3TCMOD_ENTITYTRANSLATE:
7295 // this is used in Q3 to allow the gamecode to control texcoord
7296 // scrolling on the entity, which is not supported in darkplaces yet.
7297 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7299 case Q3TCMOD_ROTATE:
7300 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7301 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7302 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7305 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7307 case Q3TCMOD_SCROLL:
7308 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7310 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7311 w = (int) tcmod->parms[0];
7312 h = (int) tcmod->parms[1];
7313 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7315 idx = (int) floor(f * w * h);
7316 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7318 case Q3TCMOD_STRETCH:
7319 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7320 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7322 case Q3TCMOD_TRANSFORM:
7323 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7324 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7325 VectorSet(tcmat + 6, 0 , 0 , 1);
7326 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7327 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7329 case Q3TCMOD_TURBULENT:
7330 // this is handled in the RSurf_PrepareVertices function
7331 matrix = identitymatrix;
7335 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7338 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7340 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7341 char name[MAX_QPATH];
7342 skinframe_t *skinframe;
7343 unsigned char pixels[296*194];
7344 strlcpy(cache->name, skinname, sizeof(cache->name));
7345 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7346 if (developer_loading.integer)
7347 Con_Printf("loading %s\n", name);
7348 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7349 if (!skinframe || !skinframe->base)
7352 fs_offset_t filesize;
7354 f = FS_LoadFile(name, tempmempool, true, &filesize);
7357 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7358 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7362 cache->skinframe = skinframe;
7365 texture_t *R_GetCurrentTexture(texture_t *t)
7368 const entity_render_t *ent = rsurface.entity;
7369 dp_model_t *model = ent->model;
7370 q3shaderinfo_layer_tcmod_t *tcmod;
7372 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7373 return t->currentframe;
7374 t->update_lastrenderframe = r_textureframe;
7375 t->update_lastrenderentity = (void *)ent;
7377 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7378 t->camera_entity = ent->entitynumber;
7380 t->camera_entity = 0;
7382 // switch to an alternate material if this is a q1bsp animated material
7384 texture_t *texture = t;
7385 int s = rsurface.ent_skinnum;
7386 if ((unsigned int)s >= (unsigned int)model->numskins)
7388 if (model->skinscenes)
7390 if (model->skinscenes[s].framecount > 1)
7391 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7393 s = model->skinscenes[s].firstframe;
7396 t = t + s * model->num_surfaces;
7399 // use an alternate animation if the entity's frame is not 0,
7400 // and only if the texture has an alternate animation
7401 if (rsurface.ent_alttextures && t->anim_total[1])
7402 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7404 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7406 texture->currentframe = t;
7409 // update currentskinframe to be a qw skin or animation frame
7410 if (rsurface.ent_qwskin >= 0)
7412 i = rsurface.ent_qwskin;
7413 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7415 r_qwskincache_size = cl.maxclients;
7417 Mem_Free(r_qwskincache);
7418 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7420 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7421 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7422 t->currentskinframe = r_qwskincache[i].skinframe;
7423 if (t->currentskinframe == NULL)
7424 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7426 else if (t->numskinframes >= 2)
7427 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7428 if (t->backgroundnumskinframes >= 2)
7429 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7431 t->currentmaterialflags = t->basematerialflags;
7432 t->currentalpha = rsurface.colormod[3];
7433 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7434 t->currentalpha *= r_wateralpha.value;
7435 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7436 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7437 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7438 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7439 if (!(rsurface.ent_flags & RENDER_LIGHT))
7440 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7441 else if (FAKELIGHT_ENABLED)
7443 // no modellight if using fakelight for the map
7445 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7447 // pick a model lighting mode
7448 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7449 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7451 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7453 if (rsurface.ent_flags & RENDER_ADDITIVE)
7454 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7455 else if (t->currentalpha < 1)
7456 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7457 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7458 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7459 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7460 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7461 if (t->backgroundnumskinframes)
7462 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7463 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7465 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7466 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7469 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7470 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7471 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7473 // there is no tcmod
7474 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7476 t->currenttexmatrix = r_waterscrollmatrix;
7477 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7479 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7481 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7482 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7485 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7486 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7487 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7488 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7490 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7491 if (t->currentskinframe->qpixels)
7492 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7493 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7494 if (!t->basetexture)
7495 t->basetexture = r_texture_notexture;
7496 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7497 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7498 t->nmaptexture = t->currentskinframe->nmap;
7499 if (!t->nmaptexture)
7500 t->nmaptexture = r_texture_blanknormalmap;
7501 t->glosstexture = r_texture_black;
7502 t->glowtexture = t->currentskinframe->glow;
7503 t->fogtexture = t->currentskinframe->fog;
7504 t->reflectmasktexture = t->currentskinframe->reflect;
7505 if (t->backgroundnumskinframes)
7507 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7508 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7509 t->backgroundglosstexture = r_texture_black;
7510 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7511 if (!t->backgroundnmaptexture)
7512 t->backgroundnmaptexture = r_texture_blanknormalmap;
7516 t->backgroundbasetexture = r_texture_white;
7517 t->backgroundnmaptexture = r_texture_blanknormalmap;
7518 t->backgroundglosstexture = r_texture_black;
7519 t->backgroundglowtexture = NULL;
7521 t->specularpower = r_shadow_glossexponent.value;
7522 // TODO: store reference values for these in the texture?
7523 t->specularscale = 0;
7524 if (r_shadow_gloss.integer > 0)
7526 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7528 if (r_shadow_glossintensity.value > 0)
7530 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7531 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7532 t->specularscale = r_shadow_glossintensity.value;
7535 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7537 t->glosstexture = r_texture_white;
7538 t->backgroundglosstexture = r_texture_white;
7539 t->specularscale = r_shadow_gloss2intensity.value;
7540 t->specularpower = r_shadow_gloss2exponent.value;
7543 t->specularscale *= t->specularscalemod;
7544 t->specularpower *= t->specularpowermod;
7546 // lightmaps mode looks bad with dlights using actual texturing, so turn
7547 // off the colormap and glossmap, but leave the normalmap on as it still
7548 // accurately represents the shading involved
7549 if (gl_lightmaps.integer)
7551 t->basetexture = r_texture_grey128;
7552 t->pantstexture = r_texture_black;
7553 t->shirttexture = r_texture_black;
7554 t->nmaptexture = r_texture_blanknormalmap;
7555 t->glosstexture = r_texture_black;
7556 t->glowtexture = NULL;
7557 t->fogtexture = NULL;
7558 t->reflectmasktexture = NULL;
7559 t->backgroundbasetexture = NULL;
7560 t->backgroundnmaptexture = r_texture_blanknormalmap;
7561 t->backgroundglosstexture = r_texture_black;
7562 t->backgroundglowtexture = NULL;
7563 t->specularscale = 0;
7564 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7567 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7568 VectorClear(t->dlightcolor);
7569 t->currentnumlayers = 0;
7570 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7572 int blendfunc1, blendfunc2;
7574 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7576 blendfunc1 = GL_SRC_ALPHA;
7577 blendfunc2 = GL_ONE;
7579 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7581 blendfunc1 = GL_SRC_ALPHA;
7582 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7584 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7586 blendfunc1 = t->customblendfunc[0];
7587 blendfunc2 = t->customblendfunc[1];
7591 blendfunc1 = GL_ONE;
7592 blendfunc2 = GL_ZERO;
7594 // don't colormod evilblend textures
7595 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7596 VectorSet(t->lightmapcolor, 1, 1, 1);
7597 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7598 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7600 // fullbright is not affected by r_refdef.lightmapintensity
7601 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]);
7602 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7603 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]);
7604 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7605 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]);
7609 vec3_t ambientcolor;
7611 // set the color tint used for lights affecting this surface
7612 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7614 // q3bsp has no lightmap updates, so the lightstylevalue that
7615 // would normally be baked into the lightmap must be
7616 // applied to the color
7617 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7618 if (model->type == mod_brushq3)
7619 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7620 colorscale *= r_refdef.lightmapintensity;
7621 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7622 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7623 // basic lit geometry
7624 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]);
7625 // add pants/shirt if needed
7626 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7627 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]);
7628 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7629 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]);
7630 // now add ambient passes if needed
7631 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7633 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]);
7634 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7635 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]);
7636 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7637 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]);
7640 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7641 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]);
7642 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7644 // if this is opaque use alpha blend which will darken the earlier
7647 // if this is an alpha blended material, all the earlier passes
7648 // were darkened by fog already, so we only need to add the fog
7649 // color ontop through the fog mask texture
7651 // if this is an additive blended material, all the earlier passes
7652 // were darkened by fog already, and we should not add fog color
7653 // (because the background was not darkened, there is no fog color
7654 // that was lost behind it).
7655 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]);
7659 return t->currentframe;
7662 rsurfacestate_t rsurface;
7664 void RSurf_ActiveWorldEntity(void)
7666 dp_model_t *model = r_refdef.scene.worldmodel;
7667 //if (rsurface.entity == r_refdef.scene.worldentity)
7669 rsurface.entity = r_refdef.scene.worldentity;
7670 rsurface.skeleton = NULL;
7671 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7672 rsurface.ent_skinnum = 0;
7673 rsurface.ent_qwskin = -1;
7674 rsurface.ent_shadertime = 0;
7675 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7676 rsurface.matrix = identitymatrix;
7677 rsurface.inversematrix = identitymatrix;
7678 rsurface.matrixscale = 1;
7679 rsurface.inversematrixscale = 1;
7680 R_EntityMatrix(&identitymatrix);
7681 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7682 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7683 rsurface.fograngerecip = r_refdef.fograngerecip;
7684 rsurface.fogheightfade = r_refdef.fogheightfade;
7685 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7686 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7687 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7688 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7689 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7690 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7691 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7692 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7693 rsurface.colormod[3] = 1;
7694 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);
7695 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7696 rsurface.frameblend[0].lerp = 1;
7697 rsurface.ent_alttextures = false;
7698 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7699 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7700 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7701 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7702 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7703 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7704 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7705 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7706 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7707 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7708 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7709 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7710 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7711 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7712 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7713 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7714 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7715 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7716 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7717 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7718 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7719 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7720 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7721 rsurface.modelelement3i = model->surfmesh.data_element3i;
7722 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7723 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7724 rsurface.modelelement3s = model->surfmesh.data_element3s;
7725 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7726 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7727 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7728 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7729 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7730 rsurface.modelsurfaces = model->data_surfaces;
7731 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7732 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7733 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7734 rsurface.modelgeneratedvertex = false;
7735 rsurface.batchgeneratedvertex = false;
7736 rsurface.batchfirstvertex = 0;
7737 rsurface.batchnumvertices = 0;
7738 rsurface.batchfirsttriangle = 0;
7739 rsurface.batchnumtriangles = 0;
7740 rsurface.batchvertex3f = NULL;
7741 rsurface.batchvertex3f_vertexbuffer = NULL;
7742 rsurface.batchvertex3f_bufferoffset = 0;
7743 rsurface.batchsvector3f = NULL;
7744 rsurface.batchsvector3f_vertexbuffer = NULL;
7745 rsurface.batchsvector3f_bufferoffset = 0;
7746 rsurface.batchtvector3f = NULL;
7747 rsurface.batchtvector3f_vertexbuffer = NULL;
7748 rsurface.batchtvector3f_bufferoffset = 0;
7749 rsurface.batchnormal3f = NULL;
7750 rsurface.batchnormal3f_vertexbuffer = NULL;
7751 rsurface.batchnormal3f_bufferoffset = 0;
7752 rsurface.batchlightmapcolor4f = NULL;
7753 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7754 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7755 rsurface.batchtexcoordtexture2f = NULL;
7756 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7757 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7758 rsurface.batchtexcoordlightmap2f = NULL;
7759 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7760 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7761 rsurface.batchvertexmesh = NULL;
7762 rsurface.batchvertexmeshbuffer = NULL;
7763 rsurface.batchvertex3fbuffer = NULL;
7764 rsurface.batchelement3i = NULL;
7765 rsurface.batchelement3i_indexbuffer = NULL;
7766 rsurface.batchelement3i_bufferoffset = 0;
7767 rsurface.batchelement3s = NULL;
7768 rsurface.batchelement3s_indexbuffer = NULL;
7769 rsurface.batchelement3s_bufferoffset = 0;
7770 rsurface.passcolor4f = NULL;
7771 rsurface.passcolor4f_vertexbuffer = NULL;
7772 rsurface.passcolor4f_bufferoffset = 0;
7775 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7777 dp_model_t *model = ent->model;
7778 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7780 rsurface.entity = (entity_render_t *)ent;
7781 rsurface.skeleton = ent->skeleton;
7782 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7783 rsurface.ent_skinnum = ent->skinnum;
7784 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;
7785 rsurface.ent_shadertime = ent->shadertime;
7786 rsurface.ent_flags = ent->flags;
7787 rsurface.matrix = ent->matrix;
7788 rsurface.inversematrix = ent->inversematrix;
7789 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7790 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7791 R_EntityMatrix(&rsurface.matrix);
7792 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7793 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7794 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7795 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7796 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7797 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7798 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7799 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7800 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7801 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7802 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7803 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7804 rsurface.colormod[3] = ent->alpha;
7805 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7806 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7807 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7808 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7809 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7810 if (ent->model->brush.submodel && !prepass)
7812 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7813 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7815 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7817 if (ent->animcache_vertex3f)
7819 rsurface.modelvertex3f = ent->animcache_vertex3f;
7820 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7821 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7822 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7823 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7824 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7825 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7827 else if (wanttangents)
7829 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7830 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7831 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7832 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7833 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7834 rsurface.modelvertexmesh = NULL;
7835 rsurface.modelvertexmeshbuffer = NULL;
7836 rsurface.modelvertex3fbuffer = NULL;
7838 else if (wantnormals)
7840 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7841 rsurface.modelsvector3f = NULL;
7842 rsurface.modeltvector3f = NULL;
7843 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7844 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7845 rsurface.modelvertexmesh = NULL;
7846 rsurface.modelvertexmeshbuffer = NULL;
7847 rsurface.modelvertex3fbuffer = NULL;
7851 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7852 rsurface.modelsvector3f = NULL;
7853 rsurface.modeltvector3f = NULL;
7854 rsurface.modelnormal3f = NULL;
7855 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7856 rsurface.modelvertexmesh = NULL;
7857 rsurface.modelvertexmeshbuffer = NULL;
7858 rsurface.modelvertex3fbuffer = NULL;
7860 rsurface.modelvertex3f_vertexbuffer = 0;
7861 rsurface.modelvertex3f_bufferoffset = 0;
7862 rsurface.modelsvector3f_vertexbuffer = 0;
7863 rsurface.modelsvector3f_bufferoffset = 0;
7864 rsurface.modeltvector3f_vertexbuffer = 0;
7865 rsurface.modeltvector3f_bufferoffset = 0;
7866 rsurface.modelnormal3f_vertexbuffer = 0;
7867 rsurface.modelnormal3f_bufferoffset = 0;
7868 rsurface.modelgeneratedvertex = true;
7872 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7873 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7874 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7875 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7876 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7877 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7878 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7879 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7880 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7881 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7882 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7883 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7884 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7885 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7886 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7887 rsurface.modelgeneratedvertex = false;
7889 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7890 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7891 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7892 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7893 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7894 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7895 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7896 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7897 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7898 rsurface.modelelement3i = model->surfmesh.data_element3i;
7899 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7900 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7901 rsurface.modelelement3s = model->surfmesh.data_element3s;
7902 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7903 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7904 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7905 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7906 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7907 rsurface.modelsurfaces = model->data_surfaces;
7908 rsurface.batchgeneratedvertex = false;
7909 rsurface.batchfirstvertex = 0;
7910 rsurface.batchnumvertices = 0;
7911 rsurface.batchfirsttriangle = 0;
7912 rsurface.batchnumtriangles = 0;
7913 rsurface.batchvertex3f = NULL;
7914 rsurface.batchvertex3f_vertexbuffer = NULL;
7915 rsurface.batchvertex3f_bufferoffset = 0;
7916 rsurface.batchsvector3f = NULL;
7917 rsurface.batchsvector3f_vertexbuffer = NULL;
7918 rsurface.batchsvector3f_bufferoffset = 0;
7919 rsurface.batchtvector3f = NULL;
7920 rsurface.batchtvector3f_vertexbuffer = NULL;
7921 rsurface.batchtvector3f_bufferoffset = 0;
7922 rsurface.batchnormal3f = NULL;
7923 rsurface.batchnormal3f_vertexbuffer = NULL;
7924 rsurface.batchnormal3f_bufferoffset = 0;
7925 rsurface.batchlightmapcolor4f = NULL;
7926 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7927 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7928 rsurface.batchtexcoordtexture2f = NULL;
7929 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7930 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7931 rsurface.batchtexcoordlightmap2f = NULL;
7932 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7933 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7934 rsurface.batchvertexmesh = NULL;
7935 rsurface.batchvertexmeshbuffer = NULL;
7936 rsurface.batchvertex3fbuffer = NULL;
7937 rsurface.batchelement3i = NULL;
7938 rsurface.batchelement3i_indexbuffer = NULL;
7939 rsurface.batchelement3i_bufferoffset = 0;
7940 rsurface.batchelement3s = NULL;
7941 rsurface.batchelement3s_indexbuffer = NULL;
7942 rsurface.batchelement3s_bufferoffset = 0;
7943 rsurface.passcolor4f = NULL;
7944 rsurface.passcolor4f_vertexbuffer = NULL;
7945 rsurface.passcolor4f_bufferoffset = 0;
7948 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)
7950 rsurface.entity = r_refdef.scene.worldentity;
7951 rsurface.skeleton = NULL;
7952 rsurface.ent_skinnum = 0;
7953 rsurface.ent_qwskin = -1;
7954 rsurface.ent_shadertime = shadertime;
7955 rsurface.ent_flags = entflags;
7956 rsurface.modelnumvertices = numvertices;
7957 rsurface.modelnumtriangles = numtriangles;
7958 rsurface.matrix = *matrix;
7959 rsurface.inversematrix = *inversematrix;
7960 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7961 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7962 R_EntityMatrix(&rsurface.matrix);
7963 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7964 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7965 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7966 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7967 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7968 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7969 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7970 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7971 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7972 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7973 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7974 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7975 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);
7976 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7977 rsurface.frameblend[0].lerp = 1;
7978 rsurface.ent_alttextures = false;
7979 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7980 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7983 rsurface.modelvertex3f = (float *)vertex3f;
7984 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7985 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7986 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7988 else if (wantnormals)
7990 rsurface.modelvertex3f = (float *)vertex3f;
7991 rsurface.modelsvector3f = NULL;
7992 rsurface.modeltvector3f = NULL;
7993 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7997 rsurface.modelvertex3f = (float *)vertex3f;
7998 rsurface.modelsvector3f = NULL;
7999 rsurface.modeltvector3f = NULL;
8000 rsurface.modelnormal3f = NULL;
8002 rsurface.modelvertexmesh = NULL;
8003 rsurface.modelvertexmeshbuffer = NULL;
8004 rsurface.modelvertex3fbuffer = NULL;
8005 rsurface.modelvertex3f_vertexbuffer = 0;
8006 rsurface.modelvertex3f_bufferoffset = 0;
8007 rsurface.modelsvector3f_vertexbuffer = 0;
8008 rsurface.modelsvector3f_bufferoffset = 0;
8009 rsurface.modeltvector3f_vertexbuffer = 0;
8010 rsurface.modeltvector3f_bufferoffset = 0;
8011 rsurface.modelnormal3f_vertexbuffer = 0;
8012 rsurface.modelnormal3f_bufferoffset = 0;
8013 rsurface.modelgeneratedvertex = true;
8014 rsurface.modellightmapcolor4f = (float *)color4f;
8015 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8016 rsurface.modellightmapcolor4f_bufferoffset = 0;
8017 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8018 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8019 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8020 rsurface.modeltexcoordlightmap2f = NULL;
8021 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8022 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8023 rsurface.modelelement3i = (int *)element3i;
8024 rsurface.modelelement3i_indexbuffer = NULL;
8025 rsurface.modelelement3i_bufferoffset = 0;
8026 rsurface.modelelement3s = (unsigned short *)element3s;
8027 rsurface.modelelement3s_indexbuffer = NULL;
8028 rsurface.modelelement3s_bufferoffset = 0;
8029 rsurface.modellightmapoffsets = NULL;
8030 rsurface.modelsurfaces = NULL;
8031 rsurface.batchgeneratedvertex = false;
8032 rsurface.batchfirstvertex = 0;
8033 rsurface.batchnumvertices = 0;
8034 rsurface.batchfirsttriangle = 0;
8035 rsurface.batchnumtriangles = 0;
8036 rsurface.batchvertex3f = NULL;
8037 rsurface.batchvertex3f_vertexbuffer = NULL;
8038 rsurface.batchvertex3f_bufferoffset = 0;
8039 rsurface.batchsvector3f = NULL;
8040 rsurface.batchsvector3f_vertexbuffer = NULL;
8041 rsurface.batchsvector3f_bufferoffset = 0;
8042 rsurface.batchtvector3f = NULL;
8043 rsurface.batchtvector3f_vertexbuffer = NULL;
8044 rsurface.batchtvector3f_bufferoffset = 0;
8045 rsurface.batchnormal3f = NULL;
8046 rsurface.batchnormal3f_vertexbuffer = NULL;
8047 rsurface.batchnormal3f_bufferoffset = 0;
8048 rsurface.batchlightmapcolor4f = NULL;
8049 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8050 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8051 rsurface.batchtexcoordtexture2f = NULL;
8052 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8053 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8054 rsurface.batchtexcoordlightmap2f = NULL;
8055 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8056 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8057 rsurface.batchvertexmesh = NULL;
8058 rsurface.batchvertexmeshbuffer = NULL;
8059 rsurface.batchvertex3fbuffer = NULL;
8060 rsurface.batchelement3i = NULL;
8061 rsurface.batchelement3i_indexbuffer = NULL;
8062 rsurface.batchelement3i_bufferoffset = 0;
8063 rsurface.batchelement3s = NULL;
8064 rsurface.batchelement3s_indexbuffer = NULL;
8065 rsurface.batchelement3s_bufferoffset = 0;
8066 rsurface.passcolor4f = NULL;
8067 rsurface.passcolor4f_vertexbuffer = NULL;
8068 rsurface.passcolor4f_bufferoffset = 0;
8070 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8072 if ((wantnormals || wanttangents) && !normal3f)
8074 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8075 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8077 if (wanttangents && !svector3f)
8079 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8080 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8081 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8086 float RSurf_FogPoint(const float *v)
8088 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8089 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8090 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8091 float FogHeightFade = r_refdef.fogheightfade;
8093 unsigned int fogmasktableindex;
8094 if (r_refdef.fogplaneviewabove)
8095 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8097 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8098 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8099 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8102 float RSurf_FogVertex(const float *v)
8104 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8105 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8106 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8107 float FogHeightFade = rsurface.fogheightfade;
8109 unsigned int fogmasktableindex;
8110 if (r_refdef.fogplaneviewabove)
8111 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8113 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8114 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8115 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8118 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8121 for (i = 0;i < numelements;i++)
8122 outelement3i[i] = inelement3i[i] + adjust;
8125 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8126 extern cvar_t gl_vbo;
8127 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8135 int surfacefirsttriangle;
8136 int surfacenumtriangles;
8137 int surfacefirstvertex;
8138 int surfaceendvertex;
8139 int surfacenumvertices;
8140 int batchnumvertices;
8141 int batchnumtriangles;
8145 qboolean dynamicvertex;
8149 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8151 q3shaderinfo_deform_t *deform;
8152 const msurface_t *surface, *firstsurface;
8153 r_vertexmesh_t *vertexmesh;
8154 if (!texturenumsurfaces)
8156 // find vertex range of this surface batch
8158 firstsurface = texturesurfacelist[0];
8159 firsttriangle = firstsurface->num_firsttriangle;
8160 batchnumvertices = 0;
8161 batchnumtriangles = 0;
8162 firstvertex = endvertex = firstsurface->num_firstvertex;
8163 for (i = 0;i < texturenumsurfaces;i++)
8165 surface = texturesurfacelist[i];
8166 if (surface != firstsurface + i)
8168 surfacefirstvertex = surface->num_firstvertex;
8169 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8170 surfacenumvertices = surface->num_vertices;
8171 surfacenumtriangles = surface->num_triangles;
8172 if (firstvertex > surfacefirstvertex)
8173 firstvertex = surfacefirstvertex;
8174 if (endvertex < surfaceendvertex)
8175 endvertex = surfaceendvertex;
8176 batchnumvertices += surfacenumvertices;
8177 batchnumtriangles += surfacenumtriangles;
8180 // we now know the vertex range used, and if there are any gaps in it
8181 rsurface.batchfirstvertex = firstvertex;
8182 rsurface.batchnumvertices = endvertex - firstvertex;
8183 rsurface.batchfirsttriangle = firsttriangle;
8184 rsurface.batchnumtriangles = batchnumtriangles;
8186 // this variable holds flags for which properties have been updated that
8187 // may require regenerating vertexmesh array...
8190 // check if any dynamic vertex processing must occur
8191 dynamicvertex = false;
8193 // if there is a chance of animated vertex colors, it's a dynamic batch
8194 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8196 dynamicvertex = true;
8197 batchneed |= BATCHNEED_NOGAPS;
8198 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8201 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8203 switch (deform->deform)
8206 case Q3DEFORM_PROJECTIONSHADOW:
8207 case Q3DEFORM_TEXT0:
8208 case Q3DEFORM_TEXT1:
8209 case Q3DEFORM_TEXT2:
8210 case Q3DEFORM_TEXT3:
8211 case Q3DEFORM_TEXT4:
8212 case Q3DEFORM_TEXT5:
8213 case Q3DEFORM_TEXT6:
8214 case Q3DEFORM_TEXT7:
8217 case Q3DEFORM_AUTOSPRITE:
8218 dynamicvertex = true;
8219 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8220 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8222 case Q3DEFORM_AUTOSPRITE2:
8223 dynamicvertex = true;
8224 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8225 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8227 case Q3DEFORM_NORMAL:
8228 dynamicvertex = true;
8229 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8230 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8233 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8234 break; // if wavefunc is a nop, ignore this transform
8235 dynamicvertex = true;
8236 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8237 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8239 case Q3DEFORM_BULGE:
8240 dynamicvertex = true;
8241 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8242 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8245 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8246 break; // if wavefunc is a nop, ignore this transform
8247 dynamicvertex = true;
8248 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8249 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8253 switch(rsurface.texture->tcgen.tcgen)
8256 case Q3TCGEN_TEXTURE:
8258 case Q3TCGEN_LIGHTMAP:
8259 dynamicvertex = true;
8260 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8261 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8263 case Q3TCGEN_VECTOR:
8264 dynamicvertex = true;
8265 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8266 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8268 case Q3TCGEN_ENVIRONMENT:
8269 dynamicvertex = true;
8270 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8271 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8274 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8276 dynamicvertex = true;
8277 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8278 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8281 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8283 dynamicvertex = true;
8284 batchneed |= BATCHNEED_NOGAPS;
8285 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8288 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8290 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8291 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8292 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8293 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8294 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8295 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8296 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8299 // when the model data has no vertex buffer (dynamic mesh), we need to
8301 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8302 batchneed |= BATCHNEED_NOGAPS;
8304 // if needsupdate, we have to do a dynamic vertex batch for sure
8305 if (needsupdate & batchneed)
8306 dynamicvertex = true;
8308 // see if we need to build vertexmesh from arrays
8309 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8310 dynamicvertex = true;
8312 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8313 // also some drivers strongly dislike firstvertex
8314 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8315 dynamicvertex = true;
8317 rsurface.batchvertex3f = rsurface.modelvertex3f;
8318 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8319 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8320 rsurface.batchsvector3f = rsurface.modelsvector3f;
8321 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8322 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8323 rsurface.batchtvector3f = rsurface.modeltvector3f;
8324 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8325 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8326 rsurface.batchnormal3f = rsurface.modelnormal3f;
8327 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8328 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8329 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8330 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8331 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8332 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8333 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8334 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8335 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8336 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8337 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8338 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8339 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8340 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8341 rsurface.batchelement3i = rsurface.modelelement3i;
8342 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8343 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8344 rsurface.batchelement3s = rsurface.modelelement3s;
8345 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8346 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8348 // if any dynamic vertex processing has to occur in software, we copy the
8349 // entire surface list together before processing to rebase the vertices
8350 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8352 // if any gaps exist and we do not have a static vertex buffer, we have to
8353 // copy the surface list together to avoid wasting upload bandwidth on the
8354 // vertices in the gaps.
8356 // if gaps exist and we have a static vertex buffer, we still have to
8357 // combine the index buffer ranges into one dynamic index buffer.
8359 // in all cases we end up with data that can be drawn in one call.
8363 // static vertex data, just set pointers...
8364 rsurface.batchgeneratedvertex = false;
8365 // if there are gaps, we want to build a combined index buffer,
8366 // otherwise use the original static buffer with an appropriate offset
8369 // build a new triangle elements array for this batch
8370 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8371 rsurface.batchfirsttriangle = 0;
8373 for (i = 0;i < texturenumsurfaces;i++)
8375 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8376 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8377 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8378 numtriangles += surfacenumtriangles;
8380 rsurface.batchelement3i_indexbuffer = NULL;
8381 rsurface.batchelement3i_bufferoffset = 0;
8382 rsurface.batchelement3s = NULL;
8383 rsurface.batchelement3s_indexbuffer = NULL;
8384 rsurface.batchelement3s_bufferoffset = 0;
8385 if (endvertex <= 65536)
8387 // make a 16bit (unsigned short) index array if possible
8388 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8389 for (i = 0;i < numtriangles*3;i++)
8390 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8396 // something needs software processing, do it for real...
8397 // we only directly handle separate array data in this case and then
8398 // generate interleaved data if needed...
8399 rsurface.batchgeneratedvertex = true;
8401 // now copy the vertex data into a combined array and make an index array
8402 // (this is what Quake3 does all the time)
8403 //if (gaps || rsurface.batchfirstvertex)
8405 rsurface.batchvertex3fbuffer = NULL;
8406 rsurface.batchvertexmesh = NULL;
8407 rsurface.batchvertexmeshbuffer = NULL;
8408 rsurface.batchvertex3f = NULL;
8409 rsurface.batchvertex3f_vertexbuffer = NULL;
8410 rsurface.batchvertex3f_bufferoffset = 0;
8411 rsurface.batchsvector3f = NULL;
8412 rsurface.batchsvector3f_vertexbuffer = NULL;
8413 rsurface.batchsvector3f_bufferoffset = 0;
8414 rsurface.batchtvector3f = NULL;
8415 rsurface.batchtvector3f_vertexbuffer = NULL;
8416 rsurface.batchtvector3f_bufferoffset = 0;
8417 rsurface.batchnormal3f = NULL;
8418 rsurface.batchnormal3f_vertexbuffer = NULL;
8419 rsurface.batchnormal3f_bufferoffset = 0;
8420 rsurface.batchlightmapcolor4f = NULL;
8421 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8422 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8423 rsurface.batchtexcoordtexture2f = NULL;
8424 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8425 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8426 rsurface.batchtexcoordlightmap2f = NULL;
8427 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8428 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8429 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8430 rsurface.batchelement3i_indexbuffer = NULL;
8431 rsurface.batchelement3i_bufferoffset = 0;
8432 rsurface.batchelement3s = NULL;
8433 rsurface.batchelement3s_indexbuffer = NULL;
8434 rsurface.batchelement3s_bufferoffset = 0;
8435 // we'll only be setting up certain arrays as needed
8436 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8437 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8438 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8439 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8440 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8441 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8442 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8444 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8445 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8447 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8448 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8449 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8450 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8451 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8452 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8455 for (i = 0;i < texturenumsurfaces;i++)
8457 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8458 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8459 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8460 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8461 // copy only the data requested
8462 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8463 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8464 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8466 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8467 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8468 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8469 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8470 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8472 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8473 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8475 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8476 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8477 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8478 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8479 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8480 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8482 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8483 numvertices += surfacenumvertices;
8484 numtriangles += surfacenumtriangles;
8487 // generate a 16bit index array as well if possible
8488 // (in general, dynamic batches fit)
8489 if (numvertices <= 65536)
8491 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8492 for (i = 0;i < numtriangles*3;i++)
8493 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8496 // since we've copied everything, the batch now starts at 0
8497 rsurface.batchfirstvertex = 0;
8498 rsurface.batchnumvertices = batchnumvertices;
8499 rsurface.batchfirsttriangle = 0;
8500 rsurface.batchnumtriangles = batchnumtriangles;
8503 // q1bsp surfaces rendered in vertex color mode have to have colors
8504 // calculated based on lightstyles
8505 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8507 // generate color arrays for the surfaces in this list
8512 const unsigned char *lm;
8513 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8514 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8515 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8517 for (i = 0;i < texturenumsurfaces;i++)
8519 surface = texturesurfacelist[i];
8520 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8521 surfacenumvertices = surface->num_vertices;
8522 if (surface->lightmapinfo->samples)
8524 for (j = 0;j < surfacenumvertices;j++)
8526 lm = surface->lightmapinfo->samples + offsets[j];
8527 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8528 VectorScale(lm, scale, c);
8529 if (surface->lightmapinfo->styles[1] != 255)
8531 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8533 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8534 VectorMA(c, scale, lm, c);
8535 if (surface->lightmapinfo->styles[2] != 255)
8538 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8539 VectorMA(c, scale, lm, c);
8540 if (surface->lightmapinfo->styles[3] != 255)
8543 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8544 VectorMA(c, scale, lm, c);
8551 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);
8557 for (j = 0;j < surfacenumvertices;j++)
8559 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8566 // if vertices are deformed (sprite flares and things in maps, possibly
8567 // water waves, bulges and other deformations), modify the copied vertices
8569 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8571 switch (deform->deform)
8574 case Q3DEFORM_PROJECTIONSHADOW:
8575 case Q3DEFORM_TEXT0:
8576 case Q3DEFORM_TEXT1:
8577 case Q3DEFORM_TEXT2:
8578 case Q3DEFORM_TEXT3:
8579 case Q3DEFORM_TEXT4:
8580 case Q3DEFORM_TEXT5:
8581 case Q3DEFORM_TEXT6:
8582 case Q3DEFORM_TEXT7:
8585 case Q3DEFORM_AUTOSPRITE:
8586 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8587 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8588 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8589 VectorNormalize(newforward);
8590 VectorNormalize(newright);
8591 VectorNormalize(newup);
8592 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8593 // rsurface.batchvertex3f_vertexbuffer = NULL;
8594 // rsurface.batchvertex3f_bufferoffset = 0;
8595 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8596 // rsurface.batchsvector3f_vertexbuffer = NULL;
8597 // rsurface.batchsvector3f_bufferoffset = 0;
8598 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8599 // rsurface.batchtvector3f_vertexbuffer = NULL;
8600 // rsurface.batchtvector3f_bufferoffset = 0;
8601 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8602 // rsurface.batchnormal3f_vertexbuffer = NULL;
8603 // rsurface.batchnormal3f_bufferoffset = 0;
8604 // a single autosprite surface can contain multiple sprites...
8605 for (j = 0;j < batchnumvertices - 3;j += 4)
8607 VectorClear(center);
8608 for (i = 0;i < 4;i++)
8609 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8610 VectorScale(center, 0.25f, center);
8611 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8612 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8613 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8614 for (i = 0;i < 4;i++)
8616 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8617 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8620 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8621 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8622 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);
8624 case Q3DEFORM_AUTOSPRITE2:
8625 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8626 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8627 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8628 VectorNormalize(newforward);
8629 VectorNormalize(newright);
8630 VectorNormalize(newup);
8631 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8632 // rsurface.batchvertex3f_vertexbuffer = NULL;
8633 // rsurface.batchvertex3f_bufferoffset = 0;
8635 const float *v1, *v2;
8645 memset(shortest, 0, sizeof(shortest));
8646 // a single autosprite surface can contain multiple sprites...
8647 for (j = 0;j < batchnumvertices - 3;j += 4)
8649 VectorClear(center);
8650 for (i = 0;i < 4;i++)
8651 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8652 VectorScale(center, 0.25f, center);
8653 // find the two shortest edges, then use them to define the
8654 // axis vectors for rotating around the central axis
8655 for (i = 0;i < 6;i++)
8657 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8658 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8659 l = VectorDistance2(v1, v2);
8660 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8662 l += (1.0f / 1024.0f);
8663 if (shortest[0].length2 > l || i == 0)
8665 shortest[1] = shortest[0];
8666 shortest[0].length2 = l;
8667 shortest[0].v1 = v1;
8668 shortest[0].v2 = v2;
8670 else if (shortest[1].length2 > l || i == 1)
8672 shortest[1].length2 = l;
8673 shortest[1].v1 = v1;
8674 shortest[1].v2 = v2;
8677 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8678 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8679 // this calculates the right vector from the shortest edge
8680 // and the up vector from the edge midpoints
8681 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8682 VectorNormalize(right);
8683 VectorSubtract(end, start, up);
8684 VectorNormalize(up);
8685 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8686 VectorSubtract(rsurface.localvieworigin, center, forward);
8687 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8688 VectorNegate(forward, forward);
8689 VectorReflect(forward, 0, up, forward);
8690 VectorNormalize(forward);
8691 CrossProduct(up, forward, newright);
8692 VectorNormalize(newright);
8693 // rotate the quad around the up axis vector, this is made
8694 // especially easy by the fact we know the quad is flat,
8695 // so we only have to subtract the center position and
8696 // measure distance along the right vector, and then
8697 // multiply that by the newright vector and add back the
8699 // we also need to subtract the old position to undo the
8700 // displacement from the center, which we do with a
8701 // DotProduct, the subtraction/addition of center is also
8702 // optimized into DotProducts here
8703 l = DotProduct(right, center);
8704 for (i = 0;i < 4;i++)
8706 v1 = rsurface.batchvertex3f + 3*(j+i);
8707 f = DotProduct(right, v1) - l;
8708 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8712 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8714 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8715 // rsurface.batchnormal3f_vertexbuffer = NULL;
8716 // rsurface.batchnormal3f_bufferoffset = 0;
8717 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8719 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8721 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8722 // rsurface.batchsvector3f_vertexbuffer = NULL;
8723 // rsurface.batchsvector3f_bufferoffset = 0;
8724 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8725 // rsurface.batchtvector3f_vertexbuffer = NULL;
8726 // rsurface.batchtvector3f_bufferoffset = 0;
8727 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);
8730 case Q3DEFORM_NORMAL:
8731 // deform the normals to make reflections wavey
8732 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8733 rsurface.batchnormal3f_vertexbuffer = NULL;
8734 rsurface.batchnormal3f_bufferoffset = 0;
8735 for (j = 0;j < batchnumvertices;j++)
8738 float *normal = rsurface.batchnormal3f + 3*j;
8739 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8740 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8741 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]);
8742 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]);
8743 VectorNormalize(normal);
8745 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8747 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8748 // rsurface.batchsvector3f_vertexbuffer = NULL;
8749 // rsurface.batchsvector3f_bufferoffset = 0;
8750 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8751 // rsurface.batchtvector3f_vertexbuffer = NULL;
8752 // rsurface.batchtvector3f_bufferoffset = 0;
8753 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);
8757 // deform vertex array to make wavey water and flags and such
8758 waveparms[0] = deform->waveparms[0];
8759 waveparms[1] = deform->waveparms[1];
8760 waveparms[2] = deform->waveparms[2];
8761 waveparms[3] = deform->waveparms[3];
8762 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8763 break; // if wavefunc is a nop, don't make a dynamic vertex array
8764 // this is how a divisor of vertex influence on deformation
8765 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8766 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8767 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8768 // rsurface.batchvertex3f_vertexbuffer = NULL;
8769 // rsurface.batchvertex3f_bufferoffset = 0;
8770 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8771 // rsurface.batchnormal3f_vertexbuffer = NULL;
8772 // rsurface.batchnormal3f_bufferoffset = 0;
8773 for (j = 0;j < batchnumvertices;j++)
8775 // if the wavefunc depends on time, evaluate it per-vertex
8778 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8779 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8781 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8783 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8784 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8785 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8787 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8788 // rsurface.batchsvector3f_vertexbuffer = NULL;
8789 // rsurface.batchsvector3f_bufferoffset = 0;
8790 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8791 // rsurface.batchtvector3f_vertexbuffer = NULL;
8792 // rsurface.batchtvector3f_bufferoffset = 0;
8793 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);
8796 case Q3DEFORM_BULGE:
8797 // deform vertex array to make the surface have moving bulges
8798 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8799 // rsurface.batchvertex3f_vertexbuffer = NULL;
8800 // rsurface.batchvertex3f_bufferoffset = 0;
8801 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8802 // rsurface.batchnormal3f_vertexbuffer = NULL;
8803 // rsurface.batchnormal3f_bufferoffset = 0;
8804 for (j = 0;j < batchnumvertices;j++)
8806 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8807 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8809 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8810 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8811 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8813 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8814 // rsurface.batchsvector3f_vertexbuffer = NULL;
8815 // rsurface.batchsvector3f_bufferoffset = 0;
8816 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8817 // rsurface.batchtvector3f_vertexbuffer = NULL;
8818 // rsurface.batchtvector3f_bufferoffset = 0;
8819 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);
8823 // deform vertex array
8824 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8825 break; // if wavefunc is a nop, don't make a dynamic vertex array
8826 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8827 VectorScale(deform->parms, scale, waveparms);
8828 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8829 // rsurface.batchvertex3f_vertexbuffer = NULL;
8830 // rsurface.batchvertex3f_bufferoffset = 0;
8831 for (j = 0;j < batchnumvertices;j++)
8832 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8837 // generate texcoords based on the chosen texcoord source
8838 switch(rsurface.texture->tcgen.tcgen)
8841 case Q3TCGEN_TEXTURE:
8843 case Q3TCGEN_LIGHTMAP:
8844 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8845 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8846 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8847 if (rsurface.batchtexcoordlightmap2f)
8848 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8850 case Q3TCGEN_VECTOR:
8851 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8852 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8853 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8854 for (j = 0;j < batchnumvertices;j++)
8856 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8857 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8860 case Q3TCGEN_ENVIRONMENT:
8861 // make environment reflections using a spheremap
8862 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8863 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8864 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8865 for (j = 0;j < batchnumvertices;j++)
8867 // identical to Q3A's method, but executed in worldspace so
8868 // carried models can be shiny too
8870 float viewer[3], d, reflected[3], worldreflected[3];
8872 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8873 // VectorNormalize(viewer);
8875 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8877 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8878 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8879 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8880 // note: this is proportinal to viewer, so we can normalize later
8882 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8883 VectorNormalize(worldreflected);
8885 // note: this sphere map only uses world x and z!
8886 // so positive and negative y will LOOK THE SAME.
8887 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8888 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8892 // the only tcmod that needs software vertex processing is turbulent, so
8893 // check for it here and apply the changes if needed
8894 // and we only support that as the first one
8895 // (handling a mixture of turbulent and other tcmods would be problematic
8896 // without punting it entirely to a software path)
8897 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8899 amplitude = rsurface.texture->tcmods[0].parms[1];
8900 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8901 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8902 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8903 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8904 for (j = 0;j < batchnumvertices;j++)
8906 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);
8907 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8911 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8913 // convert the modified arrays to vertex structs
8914 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8915 // rsurface.batchvertexmeshbuffer = NULL;
8916 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8917 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8918 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8919 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8920 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8921 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8922 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8924 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8926 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8927 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8930 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8931 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8932 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8933 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8934 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8935 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8936 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8937 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8938 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8942 void RSurf_DrawBatch(void)
8944 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8945 // through the pipeline, killing it earlier in the pipeline would have
8946 // per-surface overhead rather than per-batch overhead, so it's best to
8947 // reject it here, before it hits glDraw.
8948 if (rsurface.batchnumtriangles == 0)
8951 // batch debugging code
8952 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8958 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8959 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8962 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8964 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8966 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8967 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);
8974 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);
8977 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8979 // pick the closest matching water plane
8980 int planeindex, vertexindex, bestplaneindex = -1;
8984 r_waterstate_waterplane_t *p;
8985 qboolean prepared = false;
8987 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8989 if(p->camera_entity != rsurface.texture->camera_entity)
8994 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8996 if(rsurface.batchnumvertices == 0)
8999 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9001 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9002 d += fabs(PlaneDiff(vert, &p->plane));
9004 if (bestd > d || bestplaneindex < 0)
9007 bestplaneindex = planeindex;
9010 return bestplaneindex;
9011 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9012 // this situation though, as it might be better to render single larger
9013 // batches with useless stuff (backface culled for example) than to
9014 // render multiple smaller batches
9017 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9020 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9021 rsurface.passcolor4f_vertexbuffer = 0;
9022 rsurface.passcolor4f_bufferoffset = 0;
9023 for (i = 0;i < rsurface.batchnumvertices;i++)
9024 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9027 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9034 if (rsurface.passcolor4f)
9036 // generate color arrays
9037 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9038 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9039 rsurface.passcolor4f_vertexbuffer = 0;
9040 rsurface.passcolor4f_bufferoffset = 0;
9041 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)
9043 f = RSurf_FogVertex(v);
9052 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9053 rsurface.passcolor4f_vertexbuffer = 0;
9054 rsurface.passcolor4f_bufferoffset = 0;
9055 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9057 f = RSurf_FogVertex(v);
9066 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9073 if (!rsurface.passcolor4f)
9075 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9076 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9077 rsurface.passcolor4f_vertexbuffer = 0;
9078 rsurface.passcolor4f_bufferoffset = 0;
9079 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)
9081 f = RSurf_FogVertex(v);
9082 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9083 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9084 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9089 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9094 if (!rsurface.passcolor4f)
9096 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9097 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9098 rsurface.passcolor4f_vertexbuffer = 0;
9099 rsurface.passcolor4f_bufferoffset = 0;
9100 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9109 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9114 if (!rsurface.passcolor4f)
9116 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9117 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9118 rsurface.passcolor4f_vertexbuffer = 0;
9119 rsurface.passcolor4f_bufferoffset = 0;
9120 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9122 c2[0] = c[0] + r_refdef.scene.ambient;
9123 c2[1] = c[1] + r_refdef.scene.ambient;
9124 c2[2] = c[2] + r_refdef.scene.ambient;
9129 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9132 rsurface.passcolor4f = NULL;
9133 rsurface.passcolor4f_vertexbuffer = 0;
9134 rsurface.passcolor4f_bufferoffset = 0;
9135 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9136 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9137 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9138 GL_Color(r, g, b, a);
9139 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9143 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9145 // TODO: optimize applyfog && applycolor case
9146 // just apply fog if necessary, and tint the fog color array if necessary
9147 rsurface.passcolor4f = NULL;
9148 rsurface.passcolor4f_vertexbuffer = 0;
9149 rsurface.passcolor4f_bufferoffset = 0;
9150 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9151 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9152 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9153 GL_Color(r, g, b, a);
9157 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9160 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9161 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9162 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9163 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9164 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9165 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9166 GL_Color(r, g, b, a);
9170 static void RSurf_DrawBatch_GL11_ClampColor(void)
9175 if (!rsurface.passcolor4f)
9177 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9179 c2[0] = bound(0.0f, c1[0], 1.0f);
9180 c2[1] = bound(0.0f, c1[1], 1.0f);
9181 c2[2] = bound(0.0f, c1[2], 1.0f);
9182 c2[3] = bound(0.0f, c1[3], 1.0f);
9186 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9196 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9197 rsurface.passcolor4f_vertexbuffer = 0;
9198 rsurface.passcolor4f_bufferoffset = 0;
9199 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)
9201 f = -DotProduct(r_refdef.view.forward, n);
9203 f = f * 0.85 + 0.15; // work around so stuff won't get black
9204 f *= r_refdef.lightmapintensity;
9205 Vector4Set(c, f, f, f, 1);
9209 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9211 RSurf_DrawBatch_GL11_ApplyFakeLight();
9212 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9213 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9214 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9215 GL_Color(r, g, b, a);
9219 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9227 vec3_t ambientcolor;
9228 vec3_t diffusecolor;
9232 VectorCopy(rsurface.modellight_lightdir, lightdir);
9233 f = 0.5f * r_refdef.lightmapintensity;
9234 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9235 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9236 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9237 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9238 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9239 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9241 if (VectorLength2(diffusecolor) > 0)
9243 // q3-style directional shading
9244 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9245 rsurface.passcolor4f_vertexbuffer = 0;
9246 rsurface.passcolor4f_bufferoffset = 0;
9247 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)
9249 if ((f = DotProduct(n, lightdir)) > 0)
9250 VectorMA(ambientcolor, f, diffusecolor, c);
9252 VectorCopy(ambientcolor, c);
9259 *applycolor = false;
9263 *r = ambientcolor[0];
9264 *g = ambientcolor[1];
9265 *b = ambientcolor[2];
9266 rsurface.passcolor4f = NULL;
9267 rsurface.passcolor4f_vertexbuffer = 0;
9268 rsurface.passcolor4f_bufferoffset = 0;
9272 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9274 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9275 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9276 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9277 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9278 GL_Color(r, g, b, a);
9282 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9290 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9291 rsurface.passcolor4f_vertexbuffer = 0;
9292 rsurface.passcolor4f_bufferoffset = 0;
9294 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9296 f = 1 - RSurf_FogVertex(v);
9304 void RSurf_SetupDepthAndCulling(void)
9306 // submodels are biased to avoid z-fighting with world surfaces that they
9307 // may be exactly overlapping (avoids z-fighting artifacts on certain
9308 // doors and things in Quake maps)
9309 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9310 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9311 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9312 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9315 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9317 // transparent sky would be ridiculous
9318 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9320 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9321 skyrenderlater = true;
9322 RSurf_SetupDepthAndCulling();
9324 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9325 // skymasking on them, and Quake3 never did sky masking (unlike
9326 // software Quake and software Quake2), so disable the sky masking
9327 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9328 // and skymasking also looks very bad when noclipping outside the
9329 // level, so don't use it then either.
9330 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9332 R_Mesh_ResetTextureState();
9333 if (skyrendermasked)
9335 R_SetupShader_DepthOrShadow();
9336 // depth-only (masking)
9337 GL_ColorMask(0,0,0,0);
9338 // just to make sure that braindead drivers don't draw
9339 // anything despite that colormask...
9340 GL_BlendFunc(GL_ZERO, GL_ONE);
9341 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9342 if (rsurface.batchvertex3fbuffer)
9343 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9345 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9349 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9351 GL_BlendFunc(GL_ONE, GL_ZERO);
9352 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9353 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9354 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9357 if (skyrendermasked)
9358 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9360 R_Mesh_ResetTextureState();
9361 GL_Color(1, 1, 1, 1);
9364 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9365 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9366 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9368 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9372 // render screenspace normalmap to texture
9374 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9379 // bind lightmap texture
9381 // water/refraction/reflection/camera surfaces have to be handled specially
9382 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9384 int start, end, startplaneindex;
9385 for (start = 0;start < texturenumsurfaces;start = end)
9387 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9388 if(startplaneindex < 0)
9390 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9391 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9395 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9397 // now that we have a batch using the same planeindex, render it
9398 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9400 // render water or distortion background
9402 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));
9404 // blend surface on top
9405 GL_DepthMask(false);
9406 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9409 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9411 // render surface with reflection texture as input
9412 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9413 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));
9420 // render surface batch normally
9421 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9422 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9426 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9428 // OpenGL 1.3 path - anything not completely ancient
9429 qboolean applycolor;
9432 const texturelayer_t *layer;
9433 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);
9434 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9436 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9439 int layertexrgbscale;
9440 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9442 if (layerindex == 0)
9446 GL_AlphaTest(false);
9447 GL_DepthFunc(GL_EQUAL);
9450 GL_DepthMask(layer->depthmask && writedepth);
9451 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9452 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9454 layertexrgbscale = 4;
9455 VectorScale(layer->color, 0.25f, layercolor);
9457 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9459 layertexrgbscale = 2;
9460 VectorScale(layer->color, 0.5f, layercolor);
9464 layertexrgbscale = 1;
9465 VectorScale(layer->color, 1.0f, layercolor);
9467 layercolor[3] = layer->color[3];
9468 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9469 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9470 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9471 switch (layer->type)
9473 case TEXTURELAYERTYPE_LITTEXTURE:
9474 // single-pass lightmapped texture with 2x rgbscale
9475 R_Mesh_TexBind(0, r_texture_white);
9476 R_Mesh_TexMatrix(0, NULL);
9477 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9478 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9479 R_Mesh_TexBind(1, layer->texture);
9480 R_Mesh_TexMatrix(1, &layer->texmatrix);
9481 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9482 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9483 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9484 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9485 else if (FAKELIGHT_ENABLED)
9486 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9487 else if (rsurface.uselightmaptexture)
9488 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9490 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9492 case TEXTURELAYERTYPE_TEXTURE:
9493 // singletexture unlit texture with transparency support
9494 R_Mesh_TexBind(0, layer->texture);
9495 R_Mesh_TexMatrix(0, &layer->texmatrix);
9496 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9497 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9498 R_Mesh_TexBind(1, 0);
9499 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9500 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9502 case TEXTURELAYERTYPE_FOG:
9503 // singletexture fogging
9506 R_Mesh_TexBind(0, layer->texture);
9507 R_Mesh_TexMatrix(0, &layer->texmatrix);
9508 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9509 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9513 R_Mesh_TexBind(0, 0);
9514 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9516 R_Mesh_TexBind(1, 0);
9517 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9518 // generate a color array for the fog pass
9519 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9520 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9524 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9527 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9529 GL_DepthFunc(GL_LEQUAL);
9530 GL_AlphaTest(false);
9534 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9536 // OpenGL 1.1 - crusty old voodoo path
9539 const texturelayer_t *layer;
9540 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);
9541 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9543 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9545 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9547 if (layerindex == 0)
9551 GL_AlphaTest(false);
9552 GL_DepthFunc(GL_EQUAL);
9555 GL_DepthMask(layer->depthmask && writedepth);
9556 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9557 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9558 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9559 switch (layer->type)
9561 case TEXTURELAYERTYPE_LITTEXTURE:
9562 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9564 // two-pass lit texture with 2x rgbscale
9565 // first the lightmap pass
9566 R_Mesh_TexBind(0, r_texture_white);
9567 R_Mesh_TexMatrix(0, NULL);
9568 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9569 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9570 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9571 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9572 else if (FAKELIGHT_ENABLED)
9573 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9574 else if (rsurface.uselightmaptexture)
9575 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9577 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9578 // then apply the texture to it
9579 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9580 R_Mesh_TexBind(0, layer->texture);
9581 R_Mesh_TexMatrix(0, &layer->texmatrix);
9582 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9583 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9584 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);
9588 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9589 R_Mesh_TexBind(0, layer->texture);
9590 R_Mesh_TexMatrix(0, &layer->texmatrix);
9591 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9592 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9593 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9594 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);
9596 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);
9599 case TEXTURELAYERTYPE_TEXTURE:
9600 // singletexture unlit texture with transparency support
9601 R_Mesh_TexBind(0, layer->texture);
9602 R_Mesh_TexMatrix(0, &layer->texmatrix);
9603 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9604 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9605 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);
9607 case TEXTURELAYERTYPE_FOG:
9608 // singletexture fogging
9611 R_Mesh_TexBind(0, layer->texture);
9612 R_Mesh_TexMatrix(0, &layer->texmatrix);
9613 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9614 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9618 R_Mesh_TexBind(0, 0);
9619 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9621 // generate a color array for the fog pass
9622 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9623 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9627 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9630 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9632 GL_DepthFunc(GL_LEQUAL);
9633 GL_AlphaTest(false);
9637 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9641 r_vertexgeneric_t *batchvertex;
9644 // R_Mesh_ResetTextureState();
9645 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9647 if(rsurface.texture && rsurface.texture->currentskinframe)
9649 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9650 c[3] *= rsurface.texture->currentalpha;
9660 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9662 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9663 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9664 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9667 // brighten it up (as texture value 127 means "unlit")
9668 c[0] *= 2 * r_refdef.view.colorscale;
9669 c[1] *= 2 * r_refdef.view.colorscale;
9670 c[2] *= 2 * r_refdef.view.colorscale;
9672 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9673 c[3] *= r_wateralpha.value;
9675 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9677 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9678 GL_DepthMask(false);
9680 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9682 GL_BlendFunc(GL_ONE, GL_ONE);
9683 GL_DepthMask(false);
9685 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9687 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9688 GL_DepthMask(false);
9690 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9692 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9693 GL_DepthMask(false);
9697 GL_BlendFunc(GL_ONE, GL_ZERO);
9698 GL_DepthMask(writedepth);
9701 if (r_showsurfaces.integer == 3)
9703 rsurface.passcolor4f = NULL;
9705 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9707 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9709 rsurface.passcolor4f = NULL;
9710 rsurface.passcolor4f_vertexbuffer = 0;
9711 rsurface.passcolor4f_bufferoffset = 0;
9713 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9715 qboolean applycolor = true;
9718 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9720 r_refdef.lightmapintensity = 1;
9721 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9722 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9724 else if (FAKELIGHT_ENABLED)
9726 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9728 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9729 RSurf_DrawBatch_GL11_ApplyFakeLight();
9730 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9734 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9736 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9737 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9738 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9741 if(!rsurface.passcolor4f)
9742 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9744 RSurf_DrawBatch_GL11_ApplyAmbient();
9745 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9746 if(r_refdef.fogenabled)
9747 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9748 RSurf_DrawBatch_GL11_ClampColor();
9750 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9751 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9754 else if (!r_refdef.view.showdebug)
9756 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9757 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9758 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9760 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9761 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9763 R_Mesh_PrepareVertices_Generic_Unlock();
9766 else if (r_showsurfaces.integer == 4)
9768 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9769 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9770 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9772 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9773 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9774 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9776 R_Mesh_PrepareVertices_Generic_Unlock();
9779 else if (r_showsurfaces.integer == 2)
9782 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9783 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9784 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9786 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9787 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9788 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9789 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9790 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9791 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9792 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9794 R_Mesh_PrepareVertices_Generic_Unlock();
9795 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9799 int texturesurfaceindex;
9801 const msurface_t *surface;
9802 float surfacecolor4f[4];
9803 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9804 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9806 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9808 surface = texturesurfacelist[texturesurfaceindex];
9809 k = (int)(((size_t)surface) / sizeof(msurface_t));
9810 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9811 for (j = 0;j < surface->num_vertices;j++)
9813 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9814 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9818 R_Mesh_PrepareVertices_Generic_Unlock();
9823 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9826 RSurf_SetupDepthAndCulling();
9827 if (r_showsurfaces.integer)
9829 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9832 switch (vid.renderpath)
9834 case RENDERPATH_GL20:
9835 case RENDERPATH_D3D9:
9836 case RENDERPATH_D3D10:
9837 case RENDERPATH_D3D11:
9838 case RENDERPATH_SOFT:
9839 case RENDERPATH_GLES2:
9840 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9842 case RENDERPATH_GL13:
9843 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9845 case RENDERPATH_GL11:
9846 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9852 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9855 RSurf_SetupDepthAndCulling();
9856 if (r_showsurfaces.integer)
9858 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9861 switch (vid.renderpath)
9863 case RENDERPATH_GL20:
9864 case RENDERPATH_D3D9:
9865 case RENDERPATH_D3D10:
9866 case RENDERPATH_D3D11:
9867 case RENDERPATH_SOFT:
9868 case RENDERPATH_GLES2:
9869 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9871 case RENDERPATH_GL13:
9872 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9874 case RENDERPATH_GL11:
9875 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9881 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9884 int texturenumsurfaces, endsurface;
9886 const msurface_t *surface;
9887 #define MAXBATCH_TRANSPARENTSURFACES 256
9888 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9890 // if the model is static it doesn't matter what value we give for
9891 // wantnormals and wanttangents, so this logic uses only rules applicable
9892 // to a model, knowing that they are meaningless otherwise
9893 if (ent == r_refdef.scene.worldentity)
9894 RSurf_ActiveWorldEntity();
9895 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9896 RSurf_ActiveModelEntity(ent, false, false, false);
9899 switch (vid.renderpath)
9901 case RENDERPATH_GL20:
9902 case RENDERPATH_D3D9:
9903 case RENDERPATH_D3D10:
9904 case RENDERPATH_D3D11:
9905 case RENDERPATH_SOFT:
9906 case RENDERPATH_GLES2:
9907 RSurf_ActiveModelEntity(ent, true, true, false);
9909 case RENDERPATH_GL13:
9910 case RENDERPATH_GL11:
9911 RSurf_ActiveModelEntity(ent, true, false, false);
9916 if (r_transparentdepthmasking.integer)
9918 qboolean setup = false;
9919 for (i = 0;i < numsurfaces;i = j)
9922 surface = rsurface.modelsurfaces + surfacelist[i];
9923 texture = surface->texture;
9924 rsurface.texture = R_GetCurrentTexture(texture);
9925 rsurface.lightmaptexture = NULL;
9926 rsurface.deluxemaptexture = NULL;
9927 rsurface.uselightmaptexture = false;
9928 // scan ahead until we find a different texture
9929 endsurface = min(i + 1024, numsurfaces);
9930 texturenumsurfaces = 0;
9931 texturesurfacelist[texturenumsurfaces++] = surface;
9932 for (;j < endsurface;j++)
9934 surface = rsurface.modelsurfaces + surfacelist[j];
9935 if (texture != surface->texture)
9937 texturesurfacelist[texturenumsurfaces++] = surface;
9939 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9941 // render the range of surfaces as depth
9945 GL_ColorMask(0,0,0,0);
9948 GL_BlendFunc(GL_ONE, GL_ZERO);
9950 // R_Mesh_ResetTextureState();
9951 R_SetupShader_DepthOrShadow();
9953 RSurf_SetupDepthAndCulling();
9954 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9955 if (rsurface.batchvertex3fbuffer)
9956 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9958 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9962 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9965 for (i = 0;i < numsurfaces;i = j)
9968 surface = rsurface.modelsurfaces + surfacelist[i];
9969 texture = surface->texture;
9970 rsurface.texture = R_GetCurrentTexture(texture);
9971 // scan ahead until we find a different texture
9972 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9973 texturenumsurfaces = 0;
9974 texturesurfacelist[texturenumsurfaces++] = surface;
9975 if(FAKELIGHT_ENABLED)
9977 rsurface.lightmaptexture = NULL;
9978 rsurface.deluxemaptexture = NULL;
9979 rsurface.uselightmaptexture = false;
9980 for (;j < endsurface;j++)
9982 surface = rsurface.modelsurfaces + surfacelist[j];
9983 if (texture != surface->texture)
9985 texturesurfacelist[texturenumsurfaces++] = surface;
9990 rsurface.lightmaptexture = surface->lightmaptexture;
9991 rsurface.deluxemaptexture = surface->deluxemaptexture;
9992 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9993 for (;j < endsurface;j++)
9995 surface = rsurface.modelsurfaces + surfacelist[j];
9996 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9998 texturesurfacelist[texturenumsurfaces++] = surface;
10001 // render the range of surfaces
10002 if (ent == r_refdef.scene.worldentity)
10003 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10005 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10007 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10010 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10012 // transparent surfaces get pushed off into the transparent queue
10013 int surfacelistindex;
10014 const msurface_t *surface;
10015 vec3_t tempcenter, center;
10016 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10018 surface = texturesurfacelist[surfacelistindex];
10019 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10020 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10021 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10022 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10023 if (queueentity->transparent_offset) // transparent offset
10025 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10026 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10027 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10029 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10033 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10035 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10037 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10039 RSurf_SetupDepthAndCulling();
10040 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10041 if (rsurface.batchvertex3fbuffer)
10042 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10044 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10048 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10050 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10053 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10056 if (!rsurface.texture->currentnumlayers)
10058 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10059 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10061 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10063 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10064 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10065 else if (!rsurface.texture->currentnumlayers)
10067 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10069 // in the deferred case, transparent surfaces were queued during prepass
10070 if (!r_shadow_usingdeferredprepass)
10071 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10075 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10076 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10081 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10084 texture_t *texture;
10085 R_FrameData_SetMark();
10086 // break the surface list down into batches by texture and use of lightmapping
10087 for (i = 0;i < numsurfaces;i = j)
10090 // texture is the base texture pointer, rsurface.texture is the
10091 // current frame/skin the texture is directing us to use (for example
10092 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10093 // use skin 1 instead)
10094 texture = surfacelist[i]->texture;
10095 rsurface.texture = R_GetCurrentTexture(texture);
10096 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10098 // if this texture is not the kind we want, skip ahead to the next one
10099 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10103 if(FAKELIGHT_ENABLED || depthonly || prepass)
10105 rsurface.lightmaptexture = NULL;
10106 rsurface.deluxemaptexture = NULL;
10107 rsurface.uselightmaptexture = false;
10108 // simply scan ahead until we find a different texture or lightmap state
10109 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10114 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10115 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10116 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10117 // simply scan ahead until we find a different texture or lightmap state
10118 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10121 // render the range of surfaces
10122 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10124 R_FrameData_ReturnToMark();
10127 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10131 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10134 if (!rsurface.texture->currentnumlayers)
10136 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10137 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10139 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10141 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10142 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10143 else if (!rsurface.texture->currentnumlayers)
10145 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10147 // in the deferred case, transparent surfaces were queued during prepass
10148 if (!r_shadow_usingdeferredprepass)
10149 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10153 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10154 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10159 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10162 texture_t *texture;
10163 R_FrameData_SetMark();
10164 // break the surface list down into batches by texture and use of lightmapping
10165 for (i = 0;i < numsurfaces;i = j)
10168 // texture is the base texture pointer, rsurface.texture is the
10169 // current frame/skin the texture is directing us to use (for example
10170 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10171 // use skin 1 instead)
10172 texture = surfacelist[i]->texture;
10173 rsurface.texture = R_GetCurrentTexture(texture);
10174 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10176 // if this texture is not the kind we want, skip ahead to the next one
10177 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10181 if(FAKELIGHT_ENABLED || depthonly || prepass)
10183 rsurface.lightmaptexture = NULL;
10184 rsurface.deluxemaptexture = NULL;
10185 rsurface.uselightmaptexture = false;
10186 // simply scan ahead until we find a different texture or lightmap state
10187 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10192 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10193 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10194 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10195 // simply scan ahead until we find a different texture or lightmap state
10196 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10199 // render the range of surfaces
10200 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10202 R_FrameData_ReturnToMark();
10205 float locboxvertex3f[6*4*3] =
10207 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10208 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10209 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10210 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10211 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10212 1,0,0, 0,0,0, 0,1,0, 1,1,0
10215 unsigned short locboxelements[6*2*3] =
10220 12,13,14, 12,14,15,
10221 16,17,18, 16,18,19,
10225 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10228 cl_locnode_t *loc = (cl_locnode_t *)ent;
10230 float vertex3f[6*4*3];
10232 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10233 GL_DepthMask(false);
10234 GL_DepthRange(0, 1);
10235 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10236 GL_DepthTest(true);
10237 GL_CullFace(GL_NONE);
10238 R_EntityMatrix(&identitymatrix);
10240 // R_Mesh_ResetTextureState();
10242 i = surfacelist[0];
10243 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10244 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10245 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10246 surfacelist[0] < 0 ? 0.5f : 0.125f);
10248 if (VectorCompare(loc->mins, loc->maxs))
10250 VectorSet(size, 2, 2, 2);
10251 VectorMA(loc->mins, -0.5f, size, mins);
10255 VectorCopy(loc->mins, mins);
10256 VectorSubtract(loc->maxs, loc->mins, size);
10259 for (i = 0;i < 6*4*3;)
10260 for (j = 0;j < 3;j++, i++)
10261 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10263 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10264 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10265 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10268 void R_DrawLocs(void)
10271 cl_locnode_t *loc, *nearestloc;
10273 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10274 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10276 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10277 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10281 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10283 if (decalsystem->decals)
10284 Mem_Free(decalsystem->decals);
10285 memset(decalsystem, 0, sizeof(*decalsystem));
10288 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)
10291 tridecal_t *decals;
10294 // expand or initialize the system
10295 if (decalsystem->maxdecals <= decalsystem->numdecals)
10297 decalsystem_t old = *decalsystem;
10298 qboolean useshortelements;
10299 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10300 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10301 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)));
10302 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10303 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10304 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10305 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10306 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10307 if (decalsystem->numdecals)
10308 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10310 Mem_Free(old.decals);
10311 for (i = 0;i < decalsystem->maxdecals*3;i++)
10312 decalsystem->element3i[i] = i;
10313 if (useshortelements)
10314 for (i = 0;i < decalsystem->maxdecals*3;i++)
10315 decalsystem->element3s[i] = i;
10318 // grab a decal and search for another free slot for the next one
10319 decals = decalsystem->decals;
10320 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10321 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10323 decalsystem->freedecal = i;
10324 if (decalsystem->numdecals <= i)
10325 decalsystem->numdecals = i + 1;
10327 // initialize the decal
10329 decal->triangleindex = triangleindex;
10330 decal->surfaceindex = surfaceindex;
10331 decal->decalsequence = decalsequence;
10332 decal->color4f[0][0] = c0[0];
10333 decal->color4f[0][1] = c0[1];
10334 decal->color4f[0][2] = c0[2];
10335 decal->color4f[0][3] = 1;
10336 decal->color4f[1][0] = c1[0];
10337 decal->color4f[1][1] = c1[1];
10338 decal->color4f[1][2] = c1[2];
10339 decal->color4f[1][3] = 1;
10340 decal->color4f[2][0] = c2[0];
10341 decal->color4f[2][1] = c2[1];
10342 decal->color4f[2][2] = c2[2];
10343 decal->color4f[2][3] = 1;
10344 decal->vertex3f[0][0] = v0[0];
10345 decal->vertex3f[0][1] = v0[1];
10346 decal->vertex3f[0][2] = v0[2];
10347 decal->vertex3f[1][0] = v1[0];
10348 decal->vertex3f[1][1] = v1[1];
10349 decal->vertex3f[1][2] = v1[2];
10350 decal->vertex3f[2][0] = v2[0];
10351 decal->vertex3f[2][1] = v2[1];
10352 decal->vertex3f[2][2] = v2[2];
10353 decal->texcoord2f[0][0] = t0[0];
10354 decal->texcoord2f[0][1] = t0[1];
10355 decal->texcoord2f[1][0] = t1[0];
10356 decal->texcoord2f[1][1] = t1[1];
10357 decal->texcoord2f[2][0] = t2[0];
10358 decal->texcoord2f[2][1] = t2[1];
10361 extern cvar_t cl_decals_bias;
10362 extern cvar_t cl_decals_models;
10363 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10364 // baseparms, parms, temps
10365 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)
10370 const float *vertex3f;
10371 const float *normal3f;
10373 float points[2][9][3];
10380 e = rsurface.modelelement3i + 3*triangleindex;
10382 vertex3f = rsurface.modelvertex3f;
10383 normal3f = rsurface.modelnormal3f;
10387 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10389 index = 3*e[cornerindex];
10390 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10395 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10397 index = 3*e[cornerindex];
10398 VectorCopy(vertex3f + index, v[cornerindex]);
10403 //TriangleNormal(v[0], v[1], v[2], normal);
10404 //if (DotProduct(normal, localnormal) < 0.0f)
10406 // clip by each of the box planes formed from the projection matrix
10407 // if anything survives, we emit the decal
10408 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]);
10411 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]);
10414 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]);
10417 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]);
10420 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]);
10423 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]);
10426 // some part of the triangle survived, so we have to accept it...
10429 // dynamic always uses the original triangle
10431 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10433 index = 3*e[cornerindex];
10434 VectorCopy(vertex3f + index, v[cornerindex]);
10437 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10439 // convert vertex positions to texcoords
10440 Matrix4x4_Transform(projection, v[cornerindex], temp);
10441 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10442 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10443 // calculate distance fade from the projection origin
10444 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10445 f = bound(0.0f, f, 1.0f);
10446 c[cornerindex][0] = r * f;
10447 c[cornerindex][1] = g * f;
10448 c[cornerindex][2] = b * f;
10449 c[cornerindex][3] = 1.0f;
10450 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10453 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);
10455 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10456 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);
10458 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)
10460 matrix4x4_t projection;
10461 decalsystem_t *decalsystem;
10464 const msurface_t *surface;
10465 const msurface_t *surfaces;
10466 const int *surfacelist;
10467 const texture_t *texture;
10469 int numsurfacelist;
10470 int surfacelistindex;
10473 float localorigin[3];
10474 float localnormal[3];
10475 float localmins[3];
10476 float localmaxs[3];
10479 float planes[6][4];
10482 int bih_triangles_count;
10483 int bih_triangles[256];
10484 int bih_surfaces[256];
10486 decalsystem = &ent->decalsystem;
10487 model = ent->model;
10488 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10490 R_DecalSystem_Reset(&ent->decalsystem);
10494 if (!model->brush.data_leafs && !cl_decals_models.integer)
10496 if (decalsystem->model)
10497 R_DecalSystem_Reset(decalsystem);
10501 if (decalsystem->model != model)
10502 R_DecalSystem_Reset(decalsystem);
10503 decalsystem->model = model;
10505 RSurf_ActiveModelEntity(ent, true, false, false);
10507 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10508 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10509 VectorNormalize(localnormal);
10510 localsize = worldsize*rsurface.inversematrixscale;
10511 localmins[0] = localorigin[0] - localsize;
10512 localmins[1] = localorigin[1] - localsize;
10513 localmins[2] = localorigin[2] - localsize;
10514 localmaxs[0] = localorigin[0] + localsize;
10515 localmaxs[1] = localorigin[1] + localsize;
10516 localmaxs[2] = localorigin[2] + localsize;
10518 //VectorCopy(localnormal, planes[4]);
10519 //VectorVectors(planes[4], planes[2], planes[0]);
10520 AnglesFromVectors(angles, localnormal, NULL, false);
10521 AngleVectors(angles, planes[0], planes[2], planes[4]);
10522 VectorNegate(planes[0], planes[1]);
10523 VectorNegate(planes[2], planes[3]);
10524 VectorNegate(planes[4], planes[5]);
10525 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10526 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10527 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10528 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10529 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10530 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10535 matrix4x4_t forwardprojection;
10536 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10537 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10542 float projectionvector[4][3];
10543 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10544 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10545 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10546 projectionvector[0][0] = planes[0][0] * ilocalsize;
10547 projectionvector[0][1] = planes[1][0] * ilocalsize;
10548 projectionvector[0][2] = planes[2][0] * ilocalsize;
10549 projectionvector[1][0] = planes[0][1] * ilocalsize;
10550 projectionvector[1][1] = planes[1][1] * ilocalsize;
10551 projectionvector[1][2] = planes[2][1] * ilocalsize;
10552 projectionvector[2][0] = planes[0][2] * ilocalsize;
10553 projectionvector[2][1] = planes[1][2] * ilocalsize;
10554 projectionvector[2][2] = planes[2][2] * ilocalsize;
10555 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10556 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10557 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10558 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10562 dynamic = model->surfmesh.isanimated;
10563 numsurfacelist = model->nummodelsurfaces;
10564 surfacelist = model->sortedmodelsurfaces;
10565 surfaces = model->data_surfaces;
10568 bih_triangles_count = -1;
10571 if(model->render_bih.numleafs)
10572 bih = &model->render_bih;
10573 else if(model->collision_bih.numleafs)
10574 bih = &model->collision_bih;
10577 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10578 if(bih_triangles_count == 0)
10580 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10582 if(bih_triangles_count > 0)
10584 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10586 surfaceindex = bih_surfaces[triangleindex];
10587 surface = surfaces + surfaceindex;
10588 texture = surface->texture;
10589 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10591 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10593 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10598 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10600 surfaceindex = surfacelist[surfacelistindex];
10601 surface = surfaces + surfaceindex;
10602 // check cull box first because it rejects more than any other check
10603 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10605 // skip transparent surfaces
10606 texture = surface->texture;
10607 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10609 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10611 numtriangles = surface->num_triangles;
10612 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10613 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10618 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10619 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)
10621 int renderentityindex;
10622 float worldmins[3];
10623 float worldmaxs[3];
10624 entity_render_t *ent;
10626 if (!cl_decals_newsystem.integer)
10629 worldmins[0] = worldorigin[0] - worldsize;
10630 worldmins[1] = worldorigin[1] - worldsize;
10631 worldmins[2] = worldorigin[2] - worldsize;
10632 worldmaxs[0] = worldorigin[0] + worldsize;
10633 worldmaxs[1] = worldorigin[1] + worldsize;
10634 worldmaxs[2] = worldorigin[2] + worldsize;
10636 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10638 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10640 ent = r_refdef.scene.entities[renderentityindex];
10641 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10644 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10648 typedef struct r_decalsystem_splatqueue_s
10650 vec3_t worldorigin;
10651 vec3_t worldnormal;
10657 r_decalsystem_splatqueue_t;
10659 int r_decalsystem_numqueued = 0;
10660 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10662 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)
10664 r_decalsystem_splatqueue_t *queue;
10666 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10669 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10670 VectorCopy(worldorigin, queue->worldorigin);
10671 VectorCopy(worldnormal, queue->worldnormal);
10672 Vector4Set(queue->color, r, g, b, a);
10673 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10674 queue->worldsize = worldsize;
10675 queue->decalsequence = cl.decalsequence++;
10678 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10681 r_decalsystem_splatqueue_t *queue;
10683 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10684 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);
10685 r_decalsystem_numqueued = 0;
10688 extern cvar_t cl_decals_max;
10689 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10692 decalsystem_t *decalsystem = &ent->decalsystem;
10699 if (!decalsystem->numdecals)
10702 if (r_showsurfaces.integer)
10705 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10707 R_DecalSystem_Reset(decalsystem);
10711 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10712 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10714 if (decalsystem->lastupdatetime)
10715 frametime = (cl.time - decalsystem->lastupdatetime);
10718 decalsystem->lastupdatetime = cl.time;
10719 decal = decalsystem->decals;
10720 numdecals = decalsystem->numdecals;
10722 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10724 if (decal->color4f[0][3])
10726 decal->lived += frametime;
10727 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10729 memset(decal, 0, sizeof(*decal));
10730 if (decalsystem->freedecal > i)
10731 decalsystem->freedecal = i;
10735 decal = decalsystem->decals;
10736 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10739 // collapse the array by shuffling the tail decals into the gaps
10742 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10743 decalsystem->freedecal++;
10744 if (decalsystem->freedecal == numdecals)
10746 decal[decalsystem->freedecal] = decal[--numdecals];
10749 decalsystem->numdecals = numdecals;
10751 if (numdecals <= 0)
10753 // if there are no decals left, reset decalsystem
10754 R_DecalSystem_Reset(decalsystem);
10758 extern skinframe_t *decalskinframe;
10759 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10762 decalsystem_t *decalsystem = &ent->decalsystem;
10771 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10774 numdecals = decalsystem->numdecals;
10778 if (r_showsurfaces.integer)
10781 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10783 R_DecalSystem_Reset(decalsystem);
10787 // if the model is static it doesn't matter what value we give for
10788 // wantnormals and wanttangents, so this logic uses only rules applicable
10789 // to a model, knowing that they are meaningless otherwise
10790 if (ent == r_refdef.scene.worldentity)
10791 RSurf_ActiveWorldEntity();
10793 RSurf_ActiveModelEntity(ent, false, false, false);
10795 decalsystem->lastupdatetime = cl.time;
10796 decal = decalsystem->decals;
10798 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10800 // update vertex positions for animated models
10801 v3f = decalsystem->vertex3f;
10802 c4f = decalsystem->color4f;
10803 t2f = decalsystem->texcoord2f;
10804 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10806 if (!decal->color4f[0][3])
10809 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10812 // update color values for fading decals
10813 if (decal->lived >= cl_decals_time.value)
10814 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10818 c4f[ 0] = decal->color4f[0][0] * alpha;
10819 c4f[ 1] = decal->color4f[0][1] * alpha;
10820 c4f[ 2] = decal->color4f[0][2] * alpha;
10822 c4f[ 4] = decal->color4f[1][0] * alpha;
10823 c4f[ 5] = decal->color4f[1][1] * alpha;
10824 c4f[ 6] = decal->color4f[1][2] * alpha;
10826 c4f[ 8] = decal->color4f[2][0] * alpha;
10827 c4f[ 9] = decal->color4f[2][1] * alpha;
10828 c4f[10] = decal->color4f[2][2] * alpha;
10831 t2f[0] = decal->texcoord2f[0][0];
10832 t2f[1] = decal->texcoord2f[0][1];
10833 t2f[2] = decal->texcoord2f[1][0];
10834 t2f[3] = decal->texcoord2f[1][1];
10835 t2f[4] = decal->texcoord2f[2][0];
10836 t2f[5] = decal->texcoord2f[2][1];
10838 // update vertex positions for animated models
10839 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10841 e = rsurface.modelelement3i + 3*decal->triangleindex;
10842 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10843 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10844 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10848 VectorCopy(decal->vertex3f[0], v3f);
10849 VectorCopy(decal->vertex3f[1], v3f + 3);
10850 VectorCopy(decal->vertex3f[2], v3f + 6);
10853 if (r_refdef.fogenabled)
10855 alpha = RSurf_FogVertex(v3f);
10856 VectorScale(c4f, alpha, c4f);
10857 alpha = RSurf_FogVertex(v3f + 3);
10858 VectorScale(c4f + 4, alpha, c4f + 4);
10859 alpha = RSurf_FogVertex(v3f + 6);
10860 VectorScale(c4f + 8, alpha, c4f + 8);
10871 r_refdef.stats.drawndecals += numtris;
10873 // now render the decals all at once
10874 // (this assumes they all use one particle font texture!)
10875 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);
10876 // R_Mesh_ResetTextureState();
10877 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10878 GL_DepthMask(false);
10879 GL_DepthRange(0, 1);
10880 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10881 GL_DepthTest(true);
10882 GL_CullFace(GL_NONE);
10883 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10884 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10885 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10889 static void R_DrawModelDecals(void)
10893 // fade faster when there are too many decals
10894 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10895 for (i = 0;i < r_refdef.scene.numentities;i++)
10896 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10898 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10899 for (i = 0;i < r_refdef.scene.numentities;i++)
10900 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10901 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10903 R_DecalSystem_ApplySplatEntitiesQueue();
10905 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10906 for (i = 0;i < r_refdef.scene.numentities;i++)
10907 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10909 r_refdef.stats.totaldecals += numdecals;
10911 if (r_showsurfaces.integer)
10914 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10916 for (i = 0;i < r_refdef.scene.numentities;i++)
10918 if (!r_refdef.viewcache.entityvisible[i])
10920 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10921 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10925 extern cvar_t mod_collision_bih;
10926 void R_DrawDebugModel(void)
10928 entity_render_t *ent = rsurface.entity;
10929 int i, j, k, l, flagsmask;
10930 const msurface_t *surface;
10931 dp_model_t *model = ent->model;
10934 switch(vid.renderpath)
10936 case RENDERPATH_GL11:
10937 case RENDERPATH_GL13:
10938 case RENDERPATH_GL20:
10940 case RENDERPATH_D3D9:
10941 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10943 case RENDERPATH_D3D10:
10944 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10946 case RENDERPATH_D3D11:
10947 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10949 case RENDERPATH_SOFT:
10950 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10952 case RENDERPATH_GLES2:
10953 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10957 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10959 // R_Mesh_ResetTextureState();
10960 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10961 GL_DepthRange(0, 1);
10962 GL_DepthTest(!r_showdisabledepthtest.integer);
10963 GL_DepthMask(false);
10964 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10966 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10970 qboolean cullbox = ent == r_refdef.scene.worldentity;
10971 const q3mbrush_t *brush;
10972 const bih_t *bih = &model->collision_bih;
10973 const bih_leaf_t *bihleaf;
10974 float vertex3f[3][3];
10975 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10977 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10979 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10981 switch (bihleaf->type)
10984 brush = model->brush.data_brushes + bihleaf->itemindex;
10985 if (brush->colbrushf && brush->colbrushf->numtriangles)
10987 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);
10988 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10989 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10992 case BIH_COLLISIONTRIANGLE:
10993 triangleindex = bihleaf->itemindex;
10994 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10995 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10996 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10997 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);
10998 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10999 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11001 case BIH_RENDERTRIANGLE:
11002 triangleindex = bihleaf->itemindex;
11003 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11004 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11005 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11006 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);
11007 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11008 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11014 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11016 if (r_showtris.integer || (r_shownormals.value != 0))
11018 if (r_showdisabledepthtest.integer)
11020 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11021 GL_DepthMask(false);
11025 GL_BlendFunc(GL_ONE, GL_ZERO);
11026 GL_DepthMask(true);
11028 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11030 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11032 rsurface.texture = R_GetCurrentTexture(surface->texture);
11033 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11035 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11036 if (r_showtris.value > 0)
11038 if (!rsurface.texture->currentlayers->depthmask)
11039 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11040 else if (ent == r_refdef.scene.worldentity)
11041 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11043 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11044 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11045 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11047 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11050 if (r_shownormals.value < 0)
11052 qglBegin(GL_LINES);
11053 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11055 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11056 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11057 qglVertex3f(v[0], v[1], v[2]);
11058 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11059 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11060 qglVertex3f(v[0], v[1], v[2]);
11065 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11067 qglBegin(GL_LINES);
11068 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11070 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11071 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11072 qglVertex3f(v[0], v[1], v[2]);
11073 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11074 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11075 qglVertex3f(v[0], v[1], v[2]);
11079 qglBegin(GL_LINES);
11080 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11082 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11083 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11084 qglVertex3f(v[0], v[1], v[2]);
11085 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11086 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11087 qglVertex3f(v[0], v[1], v[2]);
11091 qglBegin(GL_LINES);
11092 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11094 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11095 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11096 qglVertex3f(v[0], v[1], v[2]);
11097 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11098 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11099 qglVertex3f(v[0], v[1], v[2]);
11106 rsurface.texture = NULL;
11110 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11111 int r_maxsurfacelist = 0;
11112 const msurface_t **r_surfacelist = NULL;
11113 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11115 int i, j, endj, flagsmask;
11116 dp_model_t *model = r_refdef.scene.worldmodel;
11117 msurface_t *surfaces;
11118 unsigned char *update;
11119 int numsurfacelist = 0;
11123 if (r_maxsurfacelist < model->num_surfaces)
11125 r_maxsurfacelist = model->num_surfaces;
11127 Mem_Free((msurface_t**)r_surfacelist);
11128 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11131 RSurf_ActiveWorldEntity();
11133 surfaces = model->data_surfaces;
11134 update = model->brushq1.lightmapupdateflags;
11136 // update light styles on this submodel
11137 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11139 model_brush_lightstyleinfo_t *style;
11140 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11142 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11144 int *list = style->surfacelist;
11145 style->value = r_refdef.scene.lightstylevalue[style->style];
11146 for (j = 0;j < style->numsurfaces;j++)
11147 update[list[j]] = true;
11152 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11156 R_DrawDebugModel();
11157 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11161 rsurface.lightmaptexture = NULL;
11162 rsurface.deluxemaptexture = NULL;
11163 rsurface.uselightmaptexture = false;
11164 rsurface.texture = NULL;
11165 rsurface.rtlight = NULL;
11166 numsurfacelist = 0;
11167 // add visible surfaces to draw list
11168 for (i = 0;i < model->nummodelsurfaces;i++)
11170 j = model->sortedmodelsurfaces[i];
11171 if (r_refdef.viewcache.world_surfacevisible[j])
11172 r_surfacelist[numsurfacelist++] = surfaces + j;
11174 // update lightmaps if needed
11175 if (model->brushq1.firstrender)
11177 model->brushq1.firstrender = false;
11178 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11180 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11184 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11185 if (r_refdef.viewcache.world_surfacevisible[j])
11187 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11189 // don't do anything if there were no surfaces
11190 if (!numsurfacelist)
11192 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11195 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11197 // add to stats if desired
11198 if (r_speeds.integer && !skysurfaces && !depthonly)
11200 r_refdef.stats.world_surfaces += numsurfacelist;
11201 for (j = 0;j < numsurfacelist;j++)
11202 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11205 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11208 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11210 int i, j, endj, flagsmask;
11211 dp_model_t *model = ent->model;
11212 msurface_t *surfaces;
11213 unsigned char *update;
11214 int numsurfacelist = 0;
11218 if (r_maxsurfacelist < model->num_surfaces)
11220 r_maxsurfacelist = model->num_surfaces;
11222 Mem_Free((msurface_t **)r_surfacelist);
11223 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11226 // if the model is static it doesn't matter what value we give for
11227 // wantnormals and wanttangents, so this logic uses only rules applicable
11228 // to a model, knowing that they are meaningless otherwise
11229 if (ent == r_refdef.scene.worldentity)
11230 RSurf_ActiveWorldEntity();
11231 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11232 RSurf_ActiveModelEntity(ent, false, false, false);
11234 RSurf_ActiveModelEntity(ent, true, true, true);
11235 else if (depthonly)
11237 switch (vid.renderpath)
11239 case RENDERPATH_GL20:
11240 case RENDERPATH_D3D9:
11241 case RENDERPATH_D3D10:
11242 case RENDERPATH_D3D11:
11243 case RENDERPATH_SOFT:
11244 case RENDERPATH_GLES2:
11245 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11247 case RENDERPATH_GL13:
11248 case RENDERPATH_GL11:
11249 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11255 switch (vid.renderpath)
11257 case RENDERPATH_GL20:
11258 case RENDERPATH_D3D9:
11259 case RENDERPATH_D3D10:
11260 case RENDERPATH_D3D11:
11261 case RENDERPATH_SOFT:
11262 case RENDERPATH_GLES2:
11263 RSurf_ActiveModelEntity(ent, true, true, false);
11265 case RENDERPATH_GL13:
11266 case RENDERPATH_GL11:
11267 RSurf_ActiveModelEntity(ent, true, false, false);
11272 surfaces = model->data_surfaces;
11273 update = model->brushq1.lightmapupdateflags;
11275 // update light styles
11276 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11278 model_brush_lightstyleinfo_t *style;
11279 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11281 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11283 int *list = style->surfacelist;
11284 style->value = r_refdef.scene.lightstylevalue[style->style];
11285 for (j = 0;j < style->numsurfaces;j++)
11286 update[list[j]] = true;
11291 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11295 R_DrawDebugModel();
11296 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11300 rsurface.lightmaptexture = NULL;
11301 rsurface.deluxemaptexture = NULL;
11302 rsurface.uselightmaptexture = false;
11303 rsurface.texture = NULL;
11304 rsurface.rtlight = NULL;
11305 numsurfacelist = 0;
11306 // add visible surfaces to draw list
11307 for (i = 0;i < model->nummodelsurfaces;i++)
11308 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11309 // don't do anything if there were no surfaces
11310 if (!numsurfacelist)
11312 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11315 // update lightmaps if needed
11319 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11324 R_BuildLightMap(ent, surfaces + j);
11329 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11331 R_BuildLightMap(ent, surfaces + j);
11332 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11334 // add to stats if desired
11335 if (r_speeds.integer && !skysurfaces && !depthonly)
11337 r_refdef.stats.entities_surfaces += numsurfacelist;
11338 for (j = 0;j < numsurfacelist;j++)
11339 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11342 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11345 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11347 static texture_t texture;
11348 static msurface_t surface;
11349 const msurface_t *surfacelist = &surface;
11351 // fake enough texture and surface state to render this geometry
11353 texture.update_lastrenderframe = -1; // regenerate this texture
11354 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11355 texture.currentskinframe = skinframe;
11356 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11357 texture.offsetmapping = OFFSETMAPPING_OFF;
11358 texture.offsetscale = 1;
11359 texture.specularscalemod = 1;
11360 texture.specularpowermod = 1;
11362 surface.texture = &texture;
11363 surface.num_triangles = numtriangles;
11364 surface.num_firsttriangle = firsttriangle;
11365 surface.num_vertices = numvertices;
11366 surface.num_firstvertex = firstvertex;
11369 rsurface.texture = R_GetCurrentTexture(surface.texture);
11370 rsurface.lightmaptexture = NULL;
11371 rsurface.deluxemaptexture = NULL;
11372 rsurface.uselightmaptexture = false;
11373 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11376 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)
11378 static msurface_t surface;
11379 const msurface_t *surfacelist = &surface;
11381 // fake enough texture and surface state to render this geometry
11382 surface.texture = texture;
11383 surface.num_triangles = numtriangles;
11384 surface.num_firsttriangle = firsttriangle;
11385 surface.num_vertices = numvertices;
11386 surface.num_firstvertex = firstvertex;
11389 rsurface.texture = R_GetCurrentTexture(surface.texture);
11390 rsurface.lightmaptexture = NULL;
11391 rsurface.deluxemaptexture = NULL;
11392 rsurface.uselightmaptexture = false;
11393 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);