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_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
76 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
77 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)"};
78 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
79 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
80 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"};
81 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"};
82 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 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"};
84 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"};
85 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"};
86 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
87 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
88 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
89 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
90 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
91 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
92 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
93 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)"};
94 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)"};
95 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
96 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
97 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
98 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
101 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
102 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
105 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
106 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
107 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."};
108 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
109 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
110 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
111 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."};
112 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
113 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
114 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
115 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
116 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"};
117 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"};
118 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
119 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
121 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
122 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
123 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"};
124 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
125 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
128 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
129 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
130 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
131 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
132 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
133 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
134 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136 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)"};
137 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"};
139 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
142 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
143 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
144 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
145 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
147 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
148 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
149 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
151 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"};
152 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"};
153 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
154 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
155 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
156 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
157 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
158 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
160 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)"};
161 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
166 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
167 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
177 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)"};
178 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
179 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"};
180 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
181 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
182 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
185 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
186 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
187 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
189 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
190 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
191 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
192 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
193 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
194 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
195 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
197 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
198 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
199 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
200 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)"};
201 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
202 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
203 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
206 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
208 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"};
210 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"};
212 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
214 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
215 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"};
216 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
217 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
218 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
219 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
220 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)"};
221 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
222 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 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"};
227 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."};
229 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)"};
231 extern cvar_t v_glslgamma;
233 extern qboolean v_flipped_state;
235 static struct r_bloomstate_s
240 int bloomwidth, bloomheight;
242 textype_t texturetype;
243 int viewfbo; // used to check if r_viewfbo cvar has changed
245 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
246 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
247 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
249 int screentexturewidth, screentextureheight;
250 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
252 int bloomtexturewidth, bloomtextureheight;
253 rtexture_t *texture_bloom;
255 // arrays for rendering the screen passes
256 float screentexcoord2f[8];
257 float bloomtexcoord2f[8];
258 float offsettexcoord2f[8];
260 r_viewport_t viewport;
264 r_waterstate_t r_waterstate;
266 /// shadow volume bsp struct with automatically growing nodes buffer
269 rtexture_t *r_texture_blanknormalmap;
270 rtexture_t *r_texture_white;
271 rtexture_t *r_texture_grey128;
272 rtexture_t *r_texture_black;
273 rtexture_t *r_texture_notexture;
274 rtexture_t *r_texture_whitecube;
275 rtexture_t *r_texture_normalizationcube;
276 rtexture_t *r_texture_fogattenuation;
277 rtexture_t *r_texture_fogheighttexture;
278 rtexture_t *r_texture_gammaramps;
279 unsigned int r_texture_gammaramps_serial;
280 //rtexture_t *r_texture_fogintensity;
281 rtexture_t *r_texture_reflectcube;
283 // TODO: hash lookups?
284 typedef struct cubemapinfo_s
291 int r_texture_numcubemaps;
292 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
294 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
295 unsigned int r_numqueries;
296 unsigned int r_maxqueries;
298 typedef struct r_qwskincache_s
300 char name[MAX_QPATH];
301 skinframe_t *skinframe;
305 static r_qwskincache_t *r_qwskincache;
306 static int r_qwskincache_size;
308 /// vertex coordinates for a quad that covers the screen exactly
309 extern const float r_screenvertex3f[12];
310 extern const float r_d3dscreenvertex3f[12];
311 const float r_screenvertex3f[12] =
318 const float r_d3dscreenvertex3f[12] =
326 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
329 for (i = 0;i < verts;i++)
340 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
343 for (i = 0;i < verts;i++)
353 // FIXME: move this to client?
356 if (gamemode == GAME_NEHAHRA)
358 Cvar_Set("gl_fogenable", "0");
359 Cvar_Set("gl_fogdensity", "0.2");
360 Cvar_Set("gl_fogred", "0.3");
361 Cvar_Set("gl_foggreen", "0.3");
362 Cvar_Set("gl_fogblue", "0.3");
364 r_refdef.fog_density = 0;
365 r_refdef.fog_red = 0;
366 r_refdef.fog_green = 0;
367 r_refdef.fog_blue = 0;
368 r_refdef.fog_alpha = 1;
369 r_refdef.fog_start = 0;
370 r_refdef.fog_end = 16384;
371 r_refdef.fog_height = 1<<30;
372 r_refdef.fog_fadedepth = 128;
373 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
376 static void R_BuildBlankTextures(void)
378 unsigned char data[4];
379 data[2] = 128; // normal X
380 data[1] = 128; // normal Y
381 data[0] = 255; // normal Z
382 data[3] = 128; // height
383 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401 static void R_BuildNoTexture(void)
404 unsigned char pix[16][16][4];
405 // this makes a light grey/dark grey checkerboard texture
406 for (y = 0;y < 16;y++)
408 for (x = 0;x < 16;x++)
410 if ((y < 8) ^ (x < 8))
426 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
429 static void R_BuildWhiteCube(void)
431 unsigned char data[6*1*1*4];
432 memset(data, 255, sizeof(data));
433 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
436 static void R_BuildNormalizationCube(void)
440 vec_t s, t, intensity;
443 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
444 for (side = 0;side < 6;side++)
446 for (y = 0;y < NORMSIZE;y++)
448 for (x = 0;x < NORMSIZE;x++)
450 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
451 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
486 intensity = 127.0f / sqrt(DotProduct(v, v));
487 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
488 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
489 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
490 data[((side*64+y)*64+x)*4+3] = 255;
494 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
498 static void R_BuildFogTexture(void)
502 unsigned char data1[FOGWIDTH][4];
503 //unsigned char data2[FOGWIDTH][4];
506 r_refdef.fogmasktable_start = r_refdef.fog_start;
507 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
508 r_refdef.fogmasktable_range = r_refdef.fogrange;
509 r_refdef.fogmasktable_density = r_refdef.fog_density;
511 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
512 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
514 d = (x * r - r_refdef.fogmasktable_start);
515 if(developer_extra.integer)
516 Con_DPrintf("%f ", d);
518 if (r_fog_exp2.integer)
519 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
521 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
522 if(developer_extra.integer)
523 Con_DPrintf(" : %f ", alpha);
524 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
525 if(developer_extra.integer)
526 Con_DPrintf(" = %f\n", alpha);
527 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
530 for (x = 0;x < FOGWIDTH;x++)
532 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
537 //data2[x][0] = 255 - b;
538 //data2[x][1] = 255 - b;
539 //data2[x][2] = 255 - b;
542 if (r_texture_fogattenuation)
544 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
550 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
554 static void R_BuildFogHeightTexture(void)
556 unsigned char *inpixels;
564 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
565 if (r_refdef.fogheighttexturename[0])
566 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
569 r_refdef.fog_height_tablesize = 0;
570 if (r_texture_fogheighttexture)
571 R_FreeTexture(r_texture_fogheighttexture);
572 r_texture_fogheighttexture = NULL;
573 if (r_refdef.fog_height_table2d)
574 Mem_Free(r_refdef.fog_height_table2d);
575 r_refdef.fog_height_table2d = NULL;
576 if (r_refdef.fog_height_table1d)
577 Mem_Free(r_refdef.fog_height_table1d);
578 r_refdef.fog_height_table1d = NULL;
582 r_refdef.fog_height_tablesize = size;
583 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
584 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
585 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
587 // LordHavoc: now the magic - what is that table2d for? it is a cooked
588 // average fog color table accounting for every fog layer between a point
589 // and the camera. (Note: attenuation is handled separately!)
590 for (y = 0;y < size;y++)
592 for (x = 0;x < size;x++)
598 for (j = x;j <= y;j++)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606 for (j = x;j >= y;j--)
608 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
614 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
615 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
616 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
619 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
622 //=======================================================================================================================================================
624 static const char *builtinshaderstring =
625 #include "shader_glsl.h"
628 const char *builtinhlslshaderstring =
629 #include "shader_hlsl.h"
632 char *glslshaderstring = NULL;
633 char *hlslshaderstring = NULL;
635 //=======================================================================================================================================================
637 typedef struct shaderpermutationinfo_s
642 shaderpermutationinfo_t;
644 typedef struct shadermodeinfo_s
646 const char *vertexfilename;
647 const char *geometryfilename;
648 const char *fragmentfilename;
654 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
655 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
657 {"#define USEDIFFUSE\n", " diffuse"},
658 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
659 {"#define USEVIEWTINT\n", " viewtint"},
660 {"#define USECOLORMAPPING\n", " colormapping"},
661 {"#define USESATURATION\n", " saturation"},
662 {"#define USEFOGINSIDE\n", " foginside"},
663 {"#define USEFOGOUTSIDE\n", " fogoutside"},
664 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
665 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
666 {"#define USEGAMMARAMPS\n", " gammaramps"},
667 {"#define USECUBEFILTER\n", " cubefilter"},
668 {"#define USEGLOW\n", " glow"},
669 {"#define USEBLOOM\n", " bloom"},
670 {"#define USESPECULAR\n", " specular"},
671 {"#define USEPOSTPROCESSING\n", " postprocessing"},
672 {"#define USEREFLECTION\n", " reflection"},
673 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
674 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
675 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
676 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
677 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
678 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
679 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
680 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
681 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
682 {"#define USEALPHAKILL\n", " alphakill"},
683 {"#define USEREFLECTCUBE\n", " reflectcube"},
684 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
685 {"#define USEBOUNCEGRID\n", " bouncegrid"},
686 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
689 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
690 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
694 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
705 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
706 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
707 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
710 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
726 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
727 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730 struct r_glsl_permutation_s;
731 typedef struct r_glsl_permutation_s
734 struct r_glsl_permutation_s *hashnext;
736 unsigned int permutation;
738 /// indicates if we have tried compiling this permutation already
740 /// 0 if compilation failed
742 // texture units assigned to each detected uniform
743 int tex_Texture_First;
744 int tex_Texture_Second;
745 int tex_Texture_GammaRamps;
746 int tex_Texture_Normal;
747 int tex_Texture_Color;
748 int tex_Texture_Gloss;
749 int tex_Texture_Glow;
750 int tex_Texture_SecondaryNormal;
751 int tex_Texture_SecondaryColor;
752 int tex_Texture_SecondaryGloss;
753 int tex_Texture_SecondaryGlow;
754 int tex_Texture_Pants;
755 int tex_Texture_Shirt;
756 int tex_Texture_FogHeightTexture;
757 int tex_Texture_FogMask;
758 int tex_Texture_Lightmap;
759 int tex_Texture_Deluxemap;
760 int tex_Texture_Attenuation;
761 int tex_Texture_Cube;
762 int tex_Texture_Refraction;
763 int tex_Texture_Reflection;
764 int tex_Texture_ShadowMap2D;
765 int tex_Texture_CubeProjection;
766 int tex_Texture_ScreenDepth;
767 int tex_Texture_ScreenNormalMap;
768 int tex_Texture_ScreenDiffuse;
769 int tex_Texture_ScreenSpecular;
770 int tex_Texture_ReflectMask;
771 int tex_Texture_ReflectCube;
772 int tex_Texture_BounceGrid;
773 /// locations of detected uniforms in program object, or -1 if not found
774 int loc_Texture_First;
775 int loc_Texture_Second;
776 int loc_Texture_GammaRamps;
777 int loc_Texture_Normal;
778 int loc_Texture_Color;
779 int loc_Texture_Gloss;
780 int loc_Texture_Glow;
781 int loc_Texture_SecondaryNormal;
782 int loc_Texture_SecondaryColor;
783 int loc_Texture_SecondaryGloss;
784 int loc_Texture_SecondaryGlow;
785 int loc_Texture_Pants;
786 int loc_Texture_Shirt;
787 int loc_Texture_FogHeightTexture;
788 int loc_Texture_FogMask;
789 int loc_Texture_Lightmap;
790 int loc_Texture_Deluxemap;
791 int loc_Texture_Attenuation;
792 int loc_Texture_Cube;
793 int loc_Texture_Refraction;
794 int loc_Texture_Reflection;
795 int loc_Texture_ShadowMap2D;
796 int loc_Texture_CubeProjection;
797 int loc_Texture_ScreenDepth;
798 int loc_Texture_ScreenNormalMap;
799 int loc_Texture_ScreenDiffuse;
800 int loc_Texture_ScreenSpecular;
801 int loc_Texture_ReflectMask;
802 int loc_Texture_ReflectCube;
803 int loc_Texture_BounceGrid;
805 int loc_BloomBlur_Parameters;
807 int loc_Color_Ambient;
808 int loc_Color_Diffuse;
809 int loc_Color_Specular;
813 int loc_DeferredColor_Ambient;
814 int loc_DeferredColor_Diffuse;
815 int loc_DeferredColor_Specular;
816 int loc_DeferredMod_Diffuse;
817 int loc_DeferredMod_Specular;
818 int loc_DistortScaleRefractReflect;
821 int loc_FogHeightFade;
823 int loc_FogPlaneViewDist;
824 int loc_FogRangeRecip;
827 int loc_LightPosition;
828 int loc_OffsetMapping_ScaleSteps;
830 int loc_ReflectColor;
831 int loc_ReflectFactor;
832 int loc_ReflectOffset;
833 int loc_RefractColor;
835 int loc_ScreenCenterRefractReflect;
836 int loc_ScreenScaleRefractReflect;
837 int loc_ScreenToDepth;
838 int loc_ShadowMap_Parameters;
839 int loc_ShadowMap_TextureScale;
840 int loc_SpecularPower;
845 int loc_ViewTintColor;
847 int loc_ModelToLight;
849 int loc_BackgroundTexMatrix;
850 int loc_ModelViewProjectionMatrix;
851 int loc_ModelViewMatrix;
852 int loc_PixelToScreenTexCoord;
853 int loc_ModelToReflectCube;
854 int loc_ShadowMapMatrix;
855 int loc_BloomColorSubtract;
856 int loc_NormalmapScrollBlend;
857 int loc_BounceGridMatrix;
858 int loc_BounceGridIntensity;
860 r_glsl_permutation_t;
862 #define SHADERPERMUTATION_HASHSIZE 256
865 // non-degradable "lightweight" shader parameters to keep the permutations simpler
866 // these can NOT degrade! only use for simple stuff
869 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
870 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
871 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
872 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
873 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
875 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
877 #define SHADERSTATICPARMS_COUNT 7
879 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
880 static int shaderstaticparms_count = 0;
882 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
883 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
884 qboolean R_CompileShader_CheckStaticParms(void)
886 static int r_compileshader_staticparms_save[1];
887 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
888 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
891 if (r_glsl_saturation_redcompensate.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
893 if (r_glsl_vertextextureblend_usebothalphas.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
895 if (r_shadow_glossexact.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
897 if (r_glsl_postprocess.integer)
899 if (r_glsl_postprocess_uservec1_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
901 if (r_glsl_postprocess_uservec2_enable.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
903 if (r_glsl_postprocess_uservec3_enable.integer)
904 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
905 if (r_glsl_postprocess_uservec4_enable.integer)
906 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
908 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
911 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
912 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
913 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
915 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
916 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
918 shaderstaticparms_count = 0;
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
922 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
923 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
924 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
925 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
926 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
927 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
930 /// information about each possible shader permutation
931 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
932 /// currently selected permutation
933 r_glsl_permutation_t *r_glsl_permutation;
934 /// storage for permutations linked in the hash table
935 memexpandablearray_t r_glsl_permutationarray;
937 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
939 //unsigned int hashdepth = 0;
940 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
941 r_glsl_permutation_t *p;
942 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
944 if (p->mode == mode && p->permutation == permutation)
946 //if (hashdepth > 10)
947 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
952 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
954 p->permutation = permutation;
955 p->hashnext = r_glsl_permutationhash[mode][hashindex];
956 r_glsl_permutationhash[mode][hashindex] = p;
957 //if (hashdepth > 10)
958 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
962 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
965 if (!filename || !filename[0])
967 if (!strcmp(filename, "glsl/default.glsl"))
969 if (!glslshaderstring)
971 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
972 if (glslshaderstring)
973 Con_DPrintf("Loading shaders from file %s...\n", filename);
975 glslshaderstring = (char *)builtinshaderstring;
977 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
978 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
981 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
984 if (printfromdisknotice)
985 Con_DPrintf("from disk %s... ", filename);
991 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
995 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
996 char *vertexstring, *geometrystring, *fragmentstring;
997 char permutationname[256];
998 int vertstrings_count = 0;
999 int geomstrings_count = 0;
1000 int fragstrings_count = 0;
1001 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1003 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1010 permutationname[0] = 0;
1011 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1012 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1013 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1015 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1017 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1018 if(vid.support.gl20shaders130)
1020 vertstrings_list[vertstrings_count++] = "#version 130\n";
1021 geomstrings_list[geomstrings_count++] = "#version 130\n";
1022 fragstrings_list[fragstrings_count++] = "#version 130\n";
1023 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1024 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1025 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1028 // the first pretext is which type of shader to compile as
1029 // (later these will all be bound together as a program object)
1030 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1031 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1032 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1034 // the second pretext is the mode (for example a light source)
1035 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1036 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1037 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1038 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1040 // now add all the permutation pretexts
1041 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1043 if (permutation & (1<<i))
1045 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1046 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1047 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1048 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1052 // keep line numbers correct
1053 vertstrings_list[vertstrings_count++] = "\n";
1054 geomstrings_list[geomstrings_count++] = "\n";
1055 fragstrings_list[fragstrings_count++] = "\n";
1060 R_CompileShader_AddStaticParms(mode, permutation);
1061 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062 vertstrings_count += shaderstaticparms_count;
1063 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064 geomstrings_count += shaderstaticparms_count;
1065 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1066 fragstrings_count += shaderstaticparms_count;
1068 // now append the shader text itself
1069 vertstrings_list[vertstrings_count++] = vertexstring;
1070 geomstrings_list[geomstrings_count++] = geometrystring;
1071 fragstrings_list[fragstrings_count++] = fragmentstring;
1073 // if any sources were NULL, clear the respective list
1075 vertstrings_count = 0;
1076 if (!geometrystring)
1077 geomstrings_count = 0;
1078 if (!fragmentstring)
1079 fragstrings_count = 0;
1081 // compile the shader program
1082 if (vertstrings_count + geomstrings_count + fragstrings_count)
1083 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1087 qglUseProgram(p->program);CHECKGLERROR
1088 // look up all the uniform variable names we care about, so we don't
1089 // have to look them up every time we set them
1091 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1092 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1093 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1094 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1095 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1096 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1097 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1098 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1099 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1100 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1101 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1102 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1103 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1104 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1105 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1106 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1107 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1108 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1109 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1110 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1111 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1112 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1113 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1114 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1115 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1116 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1117 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1118 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1119 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1120 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1121 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1122 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1123 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1124 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1125 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1126 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1127 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1128 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1129 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1130 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1131 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1132 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1133 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1134 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1135 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1136 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1137 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1138 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1139 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1140 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1141 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1142 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1143 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1144 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1145 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1146 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1147 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1148 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1149 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1150 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1151 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1152 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1153 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1154 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1155 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1156 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1157 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1158 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1159 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1160 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1161 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1162 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1163 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1164 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1165 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1166 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1167 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1168 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1169 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1170 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1171 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1172 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1173 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1174 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1175 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1176 // initialize the samplers to refer to the texture units we use
1177 p->tex_Texture_First = -1;
1178 p->tex_Texture_Second = -1;
1179 p->tex_Texture_GammaRamps = -1;
1180 p->tex_Texture_Normal = -1;
1181 p->tex_Texture_Color = -1;
1182 p->tex_Texture_Gloss = -1;
1183 p->tex_Texture_Glow = -1;
1184 p->tex_Texture_SecondaryNormal = -1;
1185 p->tex_Texture_SecondaryColor = -1;
1186 p->tex_Texture_SecondaryGloss = -1;
1187 p->tex_Texture_SecondaryGlow = -1;
1188 p->tex_Texture_Pants = -1;
1189 p->tex_Texture_Shirt = -1;
1190 p->tex_Texture_FogHeightTexture = -1;
1191 p->tex_Texture_FogMask = -1;
1192 p->tex_Texture_Lightmap = -1;
1193 p->tex_Texture_Deluxemap = -1;
1194 p->tex_Texture_Attenuation = -1;
1195 p->tex_Texture_Cube = -1;
1196 p->tex_Texture_Refraction = -1;
1197 p->tex_Texture_Reflection = -1;
1198 p->tex_Texture_ShadowMap2D = -1;
1199 p->tex_Texture_CubeProjection = -1;
1200 p->tex_Texture_ScreenDepth = -1;
1201 p->tex_Texture_ScreenNormalMap = -1;
1202 p->tex_Texture_ScreenDiffuse = -1;
1203 p->tex_Texture_ScreenSpecular = -1;
1204 p->tex_Texture_ReflectMask = -1;
1205 p->tex_Texture_ReflectCube = -1;
1206 p->tex_Texture_BounceGrid = -1;
1208 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1209 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1210 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1211 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1212 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1213 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1214 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1215 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1216 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1217 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1218 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1219 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1220 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1221 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1222 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1223 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1224 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1225 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1226 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1227 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1228 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1229 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1230 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1231 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1232 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1233 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1234 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1235 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1236 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1237 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1239 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1242 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1246 Mem_Free(vertexstring);
1248 Mem_Free(geometrystring);
1250 Mem_Free(fragmentstring);
1253 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1255 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1256 if (r_glsl_permutation != perm)
1258 r_glsl_permutation = perm;
1259 if (!r_glsl_permutation->program)
1261 if (!r_glsl_permutation->compiled)
1262 R_GLSL_CompilePermutation(perm, mode, permutation);
1263 if (!r_glsl_permutation->program)
1265 // remove features until we find a valid permutation
1267 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1269 // reduce i more quickly whenever it would not remove any bits
1270 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1271 if (!(permutation & j))
1274 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1275 if (!r_glsl_permutation->compiled)
1276 R_GLSL_CompilePermutation(perm, mode, permutation);
1277 if (r_glsl_permutation->program)
1280 if (i >= SHADERPERMUTATION_COUNT)
1282 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1283 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1284 qglUseProgram(0);CHECKGLERROR
1285 return; // no bit left to clear, entire mode is broken
1290 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1292 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1293 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1294 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1301 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1302 extern D3DCAPS9 vid_d3d9caps;
1305 struct r_hlsl_permutation_s;
1306 typedef struct r_hlsl_permutation_s
1308 /// hash lookup data
1309 struct r_hlsl_permutation_s *hashnext;
1311 unsigned int permutation;
1313 /// indicates if we have tried compiling this permutation already
1315 /// NULL if compilation failed
1316 IDirect3DVertexShader9 *vertexshader;
1317 IDirect3DPixelShader9 *pixelshader;
1319 r_hlsl_permutation_t;
1321 typedef enum D3DVSREGISTER_e
1323 D3DVSREGISTER_TexMatrix = 0, // float4x4
1324 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1325 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1326 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1327 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1328 D3DVSREGISTER_ModelToLight = 20, // float4x4
1329 D3DVSREGISTER_EyePosition = 24,
1330 D3DVSREGISTER_FogPlane = 25,
1331 D3DVSREGISTER_LightDir = 26,
1332 D3DVSREGISTER_LightPosition = 27,
1336 typedef enum D3DPSREGISTER_e
1338 D3DPSREGISTER_Alpha = 0,
1339 D3DPSREGISTER_BloomBlur_Parameters = 1,
1340 D3DPSREGISTER_ClientTime = 2,
1341 D3DPSREGISTER_Color_Ambient = 3,
1342 D3DPSREGISTER_Color_Diffuse = 4,
1343 D3DPSREGISTER_Color_Specular = 5,
1344 D3DPSREGISTER_Color_Glow = 6,
1345 D3DPSREGISTER_Color_Pants = 7,
1346 D3DPSREGISTER_Color_Shirt = 8,
1347 D3DPSREGISTER_DeferredColor_Ambient = 9,
1348 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1349 D3DPSREGISTER_DeferredColor_Specular = 11,
1350 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1351 D3DPSREGISTER_DeferredMod_Specular = 13,
1352 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1353 D3DPSREGISTER_EyePosition = 15, // unused
1354 D3DPSREGISTER_FogColor = 16,
1355 D3DPSREGISTER_FogHeightFade = 17,
1356 D3DPSREGISTER_FogPlane = 18,
1357 D3DPSREGISTER_FogPlaneViewDist = 19,
1358 D3DPSREGISTER_FogRangeRecip = 20,
1359 D3DPSREGISTER_LightColor = 21,
1360 D3DPSREGISTER_LightDir = 22, // unused
1361 D3DPSREGISTER_LightPosition = 23,
1362 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1363 D3DPSREGISTER_PixelSize = 25,
1364 D3DPSREGISTER_ReflectColor = 26,
1365 D3DPSREGISTER_ReflectFactor = 27,
1366 D3DPSREGISTER_ReflectOffset = 28,
1367 D3DPSREGISTER_RefractColor = 29,
1368 D3DPSREGISTER_Saturation = 30,
1369 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1370 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1371 D3DPSREGISTER_ScreenToDepth = 33,
1372 D3DPSREGISTER_ShadowMap_Parameters = 34,
1373 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1374 D3DPSREGISTER_SpecularPower = 36,
1375 D3DPSREGISTER_UserVec1 = 37,
1376 D3DPSREGISTER_UserVec2 = 38,
1377 D3DPSREGISTER_UserVec3 = 39,
1378 D3DPSREGISTER_UserVec4 = 40,
1379 D3DPSREGISTER_ViewTintColor = 41,
1380 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1381 D3DPSREGISTER_BloomColorSubtract = 43,
1382 D3DPSREGISTER_ViewToLight = 44, // float4x4
1383 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1384 D3DPSREGISTER_NormalmapScrollBlend = 52,
1389 /// information about each possible shader permutation
1390 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1391 /// currently selected permutation
1392 r_hlsl_permutation_t *r_hlsl_permutation;
1393 /// storage for permutations linked in the hash table
1394 memexpandablearray_t r_hlsl_permutationarray;
1396 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1398 //unsigned int hashdepth = 0;
1399 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1400 r_hlsl_permutation_t *p;
1401 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1403 if (p->mode == mode && p->permutation == permutation)
1405 //if (hashdepth > 10)
1406 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1411 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1413 p->permutation = permutation;
1414 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1415 r_hlsl_permutationhash[mode][hashindex] = p;
1416 //if (hashdepth > 10)
1417 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1421 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1424 if (!filename || !filename[0])
1426 if (!strcmp(filename, "hlsl/default.hlsl"))
1428 if (!hlslshaderstring)
1430 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1431 if (hlslshaderstring)
1432 Con_DPrintf("Loading shaders from file %s...\n", filename);
1434 hlslshaderstring = (char *)builtinhlslshaderstring;
1436 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1437 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1438 return shaderstring;
1440 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1443 if (printfromdisknotice)
1444 Con_DPrintf("from disk %s... ", filename);
1445 return shaderstring;
1447 return shaderstring;
1451 //#include <d3dx9shader.h>
1452 //#include <d3dx9mesh.h>
1454 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1456 DWORD *vsbin = NULL;
1457 DWORD *psbin = NULL;
1458 fs_offset_t vsbinsize;
1459 fs_offset_t psbinsize;
1460 // IDirect3DVertexShader9 *vs = NULL;
1461 // IDirect3DPixelShader9 *ps = NULL;
1462 ID3DXBuffer *vslog = NULL;
1463 ID3DXBuffer *vsbuffer = NULL;
1464 ID3DXConstantTable *vsconstanttable = NULL;
1465 ID3DXBuffer *pslog = NULL;
1466 ID3DXBuffer *psbuffer = NULL;
1467 ID3DXConstantTable *psconstanttable = NULL;
1470 char temp[MAX_INPUTLINE];
1471 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1472 qboolean debugshader = gl_paranoid.integer != 0;
1473 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1474 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1477 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1478 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1480 if ((!vsbin && vertstring) || (!psbin && fragstring))
1482 const char* dllnames_d3dx9 [] =
1506 dllhandle_t d3dx9_dll = NULL;
1507 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1509 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1510 dllfunction_t d3dx9_dllfuncs[] =
1512 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1513 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1514 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1517 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1519 DWORD shaderflags = 0;
1521 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1522 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1523 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1524 if (vertstring && vertstring[0])
1528 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1529 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1530 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1531 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1534 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1537 vsbinsize = vsbuffer->GetBufferSize();
1538 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1539 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1540 vsbuffer->Release();
1544 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1545 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1549 if (fragstring && fragstring[0])
1553 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1554 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1555 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1556 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1559 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1562 psbinsize = psbuffer->GetBufferSize();
1563 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1564 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1565 psbuffer->Release();
1569 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1570 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1574 Sys_UnloadLibrary(&d3dx9_dll);
1577 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1581 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1582 if (FAILED(vsresult))
1583 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1584 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1585 if (FAILED(psresult))
1586 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1588 // free the shader data
1589 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1590 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1593 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1596 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1597 int vertstring_length = 0;
1598 int geomstring_length = 0;
1599 int fragstring_length = 0;
1601 char *vertexstring, *geometrystring, *fragmentstring;
1602 char *vertstring, *geomstring, *fragstring;
1603 char permutationname[256];
1604 char cachename[256];
1605 int vertstrings_count = 0;
1606 int geomstrings_count = 0;
1607 int fragstrings_count = 0;
1608 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1610 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1615 p->vertexshader = NULL;
1616 p->pixelshader = NULL;
1618 permutationname[0] = 0;
1620 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1621 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1622 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1624 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1625 strlcat(cachename, "hlsl/", sizeof(cachename));
1627 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1628 vertstrings_count = 0;
1629 geomstrings_count = 0;
1630 fragstrings_count = 0;
1631 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1632 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1633 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1635 // the first pretext is which type of shader to compile as
1636 // (later these will all be bound together as a program object)
1637 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1638 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1639 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1641 // the second pretext is the mode (for example a light source)
1642 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1643 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1644 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1645 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1646 strlcat(cachename, modeinfo->name, sizeof(cachename));
1648 // now add all the permutation pretexts
1649 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1651 if (permutation & (1<<i))
1653 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1654 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1655 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1656 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1657 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1661 // keep line numbers correct
1662 vertstrings_list[vertstrings_count++] = "\n";
1663 geomstrings_list[geomstrings_count++] = "\n";
1664 fragstrings_list[fragstrings_count++] = "\n";
1669 R_CompileShader_AddStaticParms(mode, permutation);
1670 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671 vertstrings_count += shaderstaticparms_count;
1672 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673 geomstrings_count += shaderstaticparms_count;
1674 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1675 fragstrings_count += shaderstaticparms_count;
1677 // replace spaces in the cachename with _ characters
1678 for (i = 0;cachename[i];i++)
1679 if (cachename[i] == ' ')
1682 // now append the shader text itself
1683 vertstrings_list[vertstrings_count++] = vertexstring;
1684 geomstrings_list[geomstrings_count++] = geometrystring;
1685 fragstrings_list[fragstrings_count++] = fragmentstring;
1687 // if any sources were NULL, clear the respective list
1689 vertstrings_count = 0;
1690 if (!geometrystring)
1691 geomstrings_count = 0;
1692 if (!fragmentstring)
1693 fragstrings_count = 0;
1695 vertstring_length = 0;
1696 for (i = 0;i < vertstrings_count;i++)
1697 vertstring_length += strlen(vertstrings_list[i]);
1698 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1699 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1700 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1702 geomstring_length = 0;
1703 for (i = 0;i < geomstrings_count;i++)
1704 geomstring_length += strlen(geomstrings_list[i]);
1705 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1706 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1707 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1709 fragstring_length = 0;
1710 for (i = 0;i < fragstrings_count;i++)
1711 fragstring_length += strlen(fragstrings_list[i]);
1712 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1713 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1714 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1716 // try to load the cached shader, or generate one
1717 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1719 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1720 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1722 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1726 Mem_Free(vertstring);
1728 Mem_Free(geomstring);
1730 Mem_Free(fragstring);
1732 Mem_Free(vertexstring);
1734 Mem_Free(geometrystring);
1736 Mem_Free(fragmentstring);
1739 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 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);}
1742 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);}
1743 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);}
1744 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);}
1746 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1747 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1748 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);}
1749 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);}
1750 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);}
1751 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);}
1753 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1755 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1756 if (r_hlsl_permutation != perm)
1758 r_hlsl_permutation = perm;
1759 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1761 if (!r_hlsl_permutation->compiled)
1762 R_HLSL_CompilePermutation(perm, mode, permutation);
1763 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1765 // remove features until we find a valid permutation
1767 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1769 // reduce i more quickly whenever it would not remove any bits
1770 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1771 if (!(permutation & j))
1774 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1775 if (!r_hlsl_permutation->compiled)
1776 R_HLSL_CompilePermutation(perm, mode, permutation);
1777 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1780 if (i >= SHADERPERMUTATION_COUNT)
1782 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1783 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1784 return; // no bit left to clear, entire mode is broken
1788 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1789 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1791 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1792 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1793 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1797 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1799 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1800 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1801 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1802 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1805 void R_GLSL_Restart_f(void)
1807 unsigned int i, limit;
1808 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1809 Mem_Free(glslshaderstring);
1810 glslshaderstring = NULL;
1811 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1812 Mem_Free(hlslshaderstring);
1813 hlslshaderstring = NULL;
1814 switch(vid.renderpath)
1816 case RENDERPATH_D3D9:
1819 r_hlsl_permutation_t *p;
1820 r_hlsl_permutation = NULL;
1821 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1822 for (i = 0;i < limit;i++)
1824 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1826 if (p->vertexshader)
1827 IDirect3DVertexShader9_Release(p->vertexshader);
1829 IDirect3DPixelShader9_Release(p->pixelshader);
1830 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1833 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1837 case RENDERPATH_D3D10:
1838 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840 case RENDERPATH_D3D11:
1841 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1843 case RENDERPATH_GL20:
1844 case RENDERPATH_GLES2:
1846 r_glsl_permutation_t *p;
1847 r_glsl_permutation = NULL;
1848 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1849 for (i = 0;i < limit;i++)
1851 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1853 GL_Backend_FreeProgram(p->program);
1854 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1857 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1860 case RENDERPATH_GL11:
1861 case RENDERPATH_GL13:
1862 case RENDERPATH_GLES1:
1864 case RENDERPATH_SOFT:
1869 void R_GLSL_DumpShader_f(void)
1874 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1877 FS_Print(file, "/* The engine may define the following macros:\n");
1878 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1879 for (i = 0;i < SHADERMODE_COUNT;i++)
1880 FS_Print(file, glslshadermodeinfo[i].pretext);
1881 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1882 FS_Print(file, shaderpermutationinfo[i].pretext);
1883 FS_Print(file, "*/\n");
1884 FS_Print(file, builtinshaderstring);
1886 Con_Printf("glsl/default.glsl written\n");
1889 Con_Printf("failed to write to glsl/default.glsl\n");
1891 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1894 FS_Print(file, "/* The engine may define the following macros:\n");
1895 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1896 for (i = 0;i < SHADERMODE_COUNT;i++)
1897 FS_Print(file, hlslshadermodeinfo[i].pretext);
1898 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1899 FS_Print(file, shaderpermutationinfo[i].pretext);
1900 FS_Print(file, "*/\n");
1901 FS_Print(file, builtinhlslshaderstring);
1903 Con_Printf("hlsl/default.hlsl written\n");
1906 Con_Printf("failed to write to hlsl/default.hlsl\n");
1909 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1912 texturemode = GL_MODULATE;
1913 switch (vid.renderpath)
1915 case RENDERPATH_D3D9:
1917 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))));
1918 R_Mesh_TexBind(GL20TU_FIRST , first );
1919 R_Mesh_TexBind(GL20TU_SECOND, second);
1922 case RENDERPATH_D3D10:
1923 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1925 case RENDERPATH_D3D11:
1926 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928 case RENDERPATH_GL20:
1929 case RENDERPATH_GLES2:
1930 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))));
1931 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1932 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1934 case RENDERPATH_GL13:
1935 case RENDERPATH_GLES1:
1936 R_Mesh_TexBind(0, first );
1937 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1938 R_Mesh_TexBind(1, second);
1940 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1942 case RENDERPATH_GL11:
1943 R_Mesh_TexBind(0, first );
1945 case RENDERPATH_SOFT:
1946 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))));
1947 R_Mesh_TexBind(GL20TU_FIRST , first );
1948 R_Mesh_TexBind(GL20TU_SECOND, second);
1953 void R_SetupShader_DepthOrShadow(void)
1955 switch (vid.renderpath)
1957 case RENDERPATH_D3D9:
1959 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1962 case RENDERPATH_D3D10:
1963 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1965 case RENDERPATH_D3D11:
1966 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1968 case RENDERPATH_GL20:
1969 case RENDERPATH_GLES2:
1970 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1972 case RENDERPATH_GL13:
1973 case RENDERPATH_GLES1:
1974 R_Mesh_TexBind(0, 0);
1975 R_Mesh_TexBind(1, 0);
1977 case RENDERPATH_GL11:
1978 R_Mesh_TexBind(0, 0);
1980 case RENDERPATH_SOFT:
1981 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1986 void R_SetupShader_ShowDepth(void)
1988 switch (vid.renderpath)
1990 case RENDERPATH_D3D9:
1992 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1995 case RENDERPATH_D3D10:
1996 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998 case RENDERPATH_D3D11:
1999 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001 case RENDERPATH_GL20:
2002 case RENDERPATH_GLES2:
2003 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2005 case RENDERPATH_GL13:
2006 case RENDERPATH_GLES1:
2008 case RENDERPATH_GL11:
2010 case RENDERPATH_SOFT:
2011 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2016 extern qboolean r_shadow_usingdeferredprepass;
2017 extern cvar_t r_shadow_deferred_8bitrange;
2018 extern rtexture_t *r_shadow_attenuationgradienttexture;
2019 extern rtexture_t *r_shadow_attenuation2dtexture;
2020 extern rtexture_t *r_shadow_attenuation3dtexture;
2021 extern qboolean r_shadow_usingshadowmap2d;
2022 extern qboolean r_shadow_usingshadowmaportho;
2023 extern float r_shadow_shadowmap_texturescale[2];
2024 extern float r_shadow_shadowmap_parameters[4];
2025 extern qboolean r_shadow_shadowmapvsdct;
2026 extern qboolean r_shadow_shadowmapsampler;
2027 extern int r_shadow_shadowmappcf;
2028 extern rtexture_t *r_shadow_shadowmap2dtexture;
2029 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2030 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2031 extern matrix4x4_t r_shadow_shadowmapmatrix;
2032 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2033 extern int r_shadow_prepass_width;
2034 extern int r_shadow_prepass_height;
2035 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2036 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2037 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2038 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2039 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2041 #define BLENDFUNC_ALLOWS_COLORMOD 1
2042 #define BLENDFUNC_ALLOWS_FOG 2
2043 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2044 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2045 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2046 static int R_BlendFuncFlags(int src, int dst)
2050 // a blendfunc allows colormod if:
2051 // a) it can never keep the destination pixel invariant, or
2052 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2053 // this is to prevent unintended side effects from colormod
2055 // a blendfunc allows fog if:
2056 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2057 // this is to prevent unintended side effects from fog
2059 // these checks are the output of fogeval.pl
2061 r |= BLENDFUNC_ALLOWS_COLORMOD;
2062 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2064 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2066 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2068 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2071 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2072 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2074 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2075 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2076 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2077 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2078 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2080 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2081 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2082 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087 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)
2089 // select a permutation of the lighting shader appropriate to this
2090 // combination of texture, entity, light source, and fogging, only use the
2091 // minimum features necessary to avoid wasting rendering time in the
2092 // fragment shader on features that are not being used
2093 unsigned int permutation = 0;
2094 unsigned int mode = 0;
2096 static float dummy_colormod[3] = {1, 1, 1};
2097 float *colormod = rsurface.colormod;
2099 matrix4x4_t tempmatrix;
2100 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2101 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2102 permutation |= SHADERPERMUTATION_ALPHAKILL;
2103 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2104 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2105 if (rsurfacepass == RSURFPASS_BACKGROUND)
2107 // distorted background
2108 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2110 mode = SHADERMODE_WATER;
2111 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2113 // this is the right thing to do for wateralpha
2114 GL_BlendFunc(GL_ONE, GL_ZERO);
2115 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2119 // this is the right thing to do for entity alpha
2120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2124 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2126 mode = SHADERMODE_REFRACTION;
2127 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2128 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2132 mode = SHADERMODE_GENERIC;
2133 permutation |= SHADERPERMUTATION_DIFFUSE;
2134 GL_BlendFunc(GL_ONE, GL_ZERO);
2135 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2138 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2140 if (r_glsl_offsetmapping.integer)
2142 switch(rsurface.texture->offsetmapping)
2144 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2145 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2146 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2147 case OFFSETMAPPING_OFF: break;
2150 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2151 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2152 // normalmap (deferred prepass), may use alpha test on diffuse
2153 mode = SHADERMODE_DEFERREDGEOMETRY;
2154 GL_BlendFunc(GL_ONE, GL_ZERO);
2155 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2157 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2159 if (r_glsl_offsetmapping.integer)
2161 switch(rsurface.texture->offsetmapping)
2163 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2164 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166 case OFFSETMAPPING_OFF: break;
2169 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2172 mode = SHADERMODE_LIGHTSOURCE;
2173 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2174 permutation |= SHADERPERMUTATION_CUBEFILTER;
2175 if (diffusescale > 0)
2176 permutation |= SHADERPERMUTATION_DIFFUSE;
2177 if (specularscale > 0)
2178 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2179 if (r_refdef.fogenabled)
2180 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2181 if (rsurface.texture->colormapping)
2182 permutation |= SHADERPERMUTATION_COLORMAPPING;
2183 if (r_shadow_usingshadowmap2d)
2185 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2186 if(r_shadow_shadowmapvsdct)
2187 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2189 if (r_shadow_shadowmapsampler)
2190 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2191 if (r_shadow_shadowmappcf > 1)
2192 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2193 else if (r_shadow_shadowmappcf)
2194 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2196 if (rsurface.texture->reflectmasktexture)
2197 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2198 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2199 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2201 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2203 if (r_glsl_offsetmapping.integer)
2205 switch(rsurface.texture->offsetmapping)
2207 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2208 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2209 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2210 case OFFSETMAPPING_OFF: break;
2213 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2214 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2215 // unshaded geometry (fullbright or ambient model lighting)
2216 mode = SHADERMODE_FLATCOLOR;
2217 ambientscale = diffusescale = specularscale = 0;
2218 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2219 permutation |= SHADERPERMUTATION_GLOW;
2220 if (r_refdef.fogenabled)
2221 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2222 if (rsurface.texture->colormapping)
2223 permutation |= SHADERPERMUTATION_COLORMAPPING;
2224 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2226 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2227 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2229 if (r_shadow_shadowmapsampler)
2230 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2231 if (r_shadow_shadowmappcf > 1)
2232 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2233 else if (r_shadow_shadowmappcf)
2234 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2236 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2237 permutation |= SHADERPERMUTATION_REFLECTION;
2238 if (rsurface.texture->reflectmasktexture)
2239 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2240 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2241 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2243 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2245 if (r_glsl_offsetmapping.integer)
2247 switch(rsurface.texture->offsetmapping)
2249 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2250 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2252 case OFFSETMAPPING_OFF: break;
2255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2256 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2257 // directional model lighting
2258 mode = SHADERMODE_LIGHTDIRECTION;
2259 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2260 permutation |= SHADERPERMUTATION_GLOW;
2261 permutation |= SHADERPERMUTATION_DIFFUSE;
2262 if (specularscale > 0)
2263 permutation |= SHADERPERMUTATION_SPECULAR;
2264 if (r_refdef.fogenabled)
2265 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2266 if (rsurface.texture->colormapping)
2267 permutation |= SHADERPERMUTATION_COLORMAPPING;
2268 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2270 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2271 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2273 if (r_shadow_shadowmapsampler)
2274 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2275 if (r_shadow_shadowmappcf > 1)
2276 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2277 else if (r_shadow_shadowmappcf)
2278 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2280 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2281 permutation |= SHADERPERMUTATION_REFLECTION;
2282 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2283 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2284 if (rsurface.texture->reflectmasktexture)
2285 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2286 if (r_shadow_bouncegridtexture)
2288 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2289 if (r_shadow_bouncegriddirectional)
2290 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2292 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2295 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2297 if (r_glsl_offsetmapping.integer)
2299 switch(rsurface.texture->offsetmapping)
2301 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2302 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304 case OFFSETMAPPING_OFF: break;
2307 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2308 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2309 // ambient model lighting
2310 mode = SHADERMODE_LIGHTDIRECTION;
2311 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2312 permutation |= SHADERPERMUTATION_GLOW;
2313 if (r_refdef.fogenabled)
2314 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2315 if (rsurface.texture->colormapping)
2316 permutation |= SHADERPERMUTATION_COLORMAPPING;
2317 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2319 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2320 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322 if (r_shadow_shadowmapsampler)
2323 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2324 if (r_shadow_shadowmappcf > 1)
2325 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2326 else if (r_shadow_shadowmappcf)
2327 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2329 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330 permutation |= SHADERPERMUTATION_REFLECTION;
2331 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333 if (rsurface.texture->reflectmasktexture)
2334 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335 if (r_shadow_bouncegridtexture)
2337 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338 if (r_shadow_bouncegriddirectional)
2339 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2341 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346 if (r_glsl_offsetmapping.integer)
2348 switch(rsurface.texture->offsetmapping)
2350 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2351 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2353 case OFFSETMAPPING_OFF: break;
2356 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2357 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2359 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360 permutation |= SHADERPERMUTATION_GLOW;
2361 if (r_refdef.fogenabled)
2362 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2363 if (rsurface.texture->colormapping)
2364 permutation |= SHADERPERMUTATION_COLORMAPPING;
2365 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2367 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2368 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2370 if (r_shadow_shadowmapsampler)
2371 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2372 if (r_shadow_shadowmappcf > 1)
2373 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2374 else if (r_shadow_shadowmappcf)
2375 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378 permutation |= SHADERPERMUTATION_REFLECTION;
2379 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2380 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381 if (rsurface.texture->reflectmasktexture)
2382 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383 if (FAKELIGHT_ENABLED)
2385 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2386 mode = SHADERMODE_FAKELIGHT;
2387 permutation |= SHADERPERMUTATION_DIFFUSE;
2388 if (specularscale > 0)
2389 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2391 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2393 // deluxemapping (light direction texture)
2394 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2395 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2397 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2398 permutation |= SHADERPERMUTATION_DIFFUSE;
2399 if (specularscale > 0)
2400 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2404 // fake deluxemapping (uniform light direction in tangentspace)
2405 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2406 permutation |= SHADERPERMUTATION_DIFFUSE;
2407 if (specularscale > 0)
2408 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2410 else if (rsurface.uselightmaptexture)
2412 // ordinary lightmapping (q1bsp, q3bsp)
2413 mode = SHADERMODE_LIGHTMAP;
2417 // ordinary vertex coloring (q3bsp)
2418 mode = SHADERMODE_VERTEXCOLOR;
2420 if (r_shadow_bouncegridtexture)
2422 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2423 if (r_shadow_bouncegriddirectional)
2424 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2426 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2427 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2429 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2430 colormod = dummy_colormod;
2431 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2432 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2433 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2434 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2435 switch(vid.renderpath)
2437 case RENDERPATH_D3D9:
2439 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);
2440 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2441 R_SetupShader_SetPermutationHLSL(mode, permutation);
2442 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2443 if (mode == SHADERMODE_LIGHTSOURCE)
2445 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2446 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2450 if (mode == SHADERMODE_LIGHTDIRECTION)
2452 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2455 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2456 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2457 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2458 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2459 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2461 if (mode == SHADERMODE_LIGHTSOURCE)
2463 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2464 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2465 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2466 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2467 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2469 // additive passes are only darkened by fog, not tinted
2470 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2471 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2475 if (mode == SHADERMODE_FLATCOLOR)
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2479 else if (mode == SHADERMODE_LIGHTDIRECTION)
2481 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]);
2482 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2483 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);
2484 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);
2485 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2486 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2487 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2491 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2492 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2493 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);
2494 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);
2495 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2497 // additive passes are only darkened by fog, not tinted
2498 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2499 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2501 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2502 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);
2503 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2504 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2505 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2506 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2507 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2508 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2509 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2510 if (mode == SHADERMODE_WATER)
2511 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2513 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2514 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2515 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2516 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));
2517 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2518 if (rsurface.texture->pantstexture)
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2521 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2522 if (rsurface.texture->shirttexture)
2523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2526 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2528 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2529 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2530 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2531 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2532 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2533 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2534 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2536 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2537 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2539 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2540 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2541 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2542 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2543 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2544 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2545 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2546 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2547 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2548 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2549 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2550 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2551 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2552 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2553 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2554 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2555 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2556 if (rsurfacepass == RSURFPASS_BACKGROUND)
2558 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2559 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2560 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2564 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2566 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2567 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2568 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2569 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2570 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2572 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2573 if (rsurface.rtlight)
2575 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2576 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2581 case RENDERPATH_D3D10:
2582 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2584 case RENDERPATH_D3D11:
2585 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2587 case RENDERPATH_GL20:
2588 case RENDERPATH_GLES2:
2589 if (!vid.useinterleavedarrays)
2591 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);
2592 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2593 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2594 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2595 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2596 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2597 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2598 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2602 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);
2603 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2605 R_SetupShader_SetPermutationGLSL(mode, permutation);
2606 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2607 if (mode == SHADERMODE_LIGHTSOURCE)
2609 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2610 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2611 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2612 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2613 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2614 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);
2616 // additive passes are only darkened by fog, not tinted
2617 if (r_glsl_permutation->loc_FogColor >= 0)
2618 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2619 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2623 if (mode == SHADERMODE_FLATCOLOR)
2625 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2627 else if (mode == SHADERMODE_LIGHTDIRECTION)
2629 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]);
2630 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]);
2631 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);
2632 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);
2633 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);
2634 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]);
2635 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]);
2639 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]);
2640 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]);
2641 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);
2642 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);
2643 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);
2645 // additive passes are only darkened by fog, not tinted
2646 if (r_glsl_permutation->loc_FogColor >= 0)
2648 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2649 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2651 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2653 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);
2654 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]);
2655 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]);
2656 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]);
2657 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]);
2658 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2659 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2660 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2661 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]);
2663 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2664 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2665 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2666 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]);
2667 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]);
2669 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2670 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));
2671 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2672 if (r_glsl_permutation->loc_Color_Pants >= 0)
2674 if (rsurface.texture->pantstexture)
2675 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2677 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2679 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2681 if (rsurface.texture->shirttexture)
2682 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2684 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2686 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]);
2687 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2688 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2689 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2690 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2691 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2692 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2693 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2694 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2696 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]);
2697 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698 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);}
2699 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2701 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2702 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2703 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2704 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2705 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2706 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2707 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2708 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2709 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2710 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2711 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2712 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2713 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2714 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2715 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);
2716 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2717 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2718 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2721 if (rsurfacepass == RSURFPASS_BACKGROUND)
2723 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);
2724 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);
2725 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);
2729 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);
2731 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2732 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2733 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2734 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2735 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2737 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2738 if (rsurface.rtlight)
2740 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2741 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2744 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2747 case RENDERPATH_GL11:
2748 case RENDERPATH_GL13:
2749 case RENDERPATH_GLES1:
2751 case RENDERPATH_SOFT:
2752 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);
2753 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2754 R_SetupShader_SetPermutationSoft(mode, permutation);
2755 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2756 if (mode == SHADERMODE_LIGHTSOURCE)
2758 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2762 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2763 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2765 // additive passes are only darkened by fog, not tinted
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2767 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2771 if (mode == SHADERMODE_FLATCOLOR)
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2775 else if (mode == SHADERMODE_LIGHTDIRECTION)
2777 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]);
2778 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2782 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]);
2783 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2789 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);
2790 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);
2791 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2793 // additive passes are only darkened by fog, not tinted
2794 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2795 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2797 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2798 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);
2799 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2800 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2801 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]);
2802 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]);
2803 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2804 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2805 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2806 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2808 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2809 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2810 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2811 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2812 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]);
2814 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2815 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));
2816 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2817 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2819 if (rsurface.texture->pantstexture)
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2824 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2826 if (rsurface.texture->shirttexture)
2827 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2829 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2831 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2832 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2833 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2834 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2835 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2836 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2837 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2838 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2839 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2841 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2842 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2844 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2845 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2846 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2847 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2848 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2849 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2850 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2851 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2852 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2853 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2854 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2855 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2856 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2857 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2858 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2859 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2860 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2861 if (rsurfacepass == RSURFPASS_BACKGROUND)
2863 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2864 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2865 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2869 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2871 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2872 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2873 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2874 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2875 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2877 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2878 if (rsurface.rtlight)
2880 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2881 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2888 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2890 // select a permutation of the lighting shader appropriate to this
2891 // combination of texture, entity, light source, and fogging, only use the
2892 // minimum features necessary to avoid wasting rendering time in the
2893 // fragment shader on features that are not being used
2894 unsigned int permutation = 0;
2895 unsigned int mode = 0;
2896 const float *lightcolorbase = rtlight->currentcolor;
2897 float ambientscale = rtlight->ambientscale;
2898 float diffusescale = rtlight->diffusescale;
2899 float specularscale = rtlight->specularscale;
2900 // this is the location of the light in view space
2901 vec3_t viewlightorigin;
2902 // this transforms from view space (camera) to light space (cubemap)
2903 matrix4x4_t viewtolight;
2904 matrix4x4_t lighttoview;
2905 float viewtolight16f[16];
2906 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2908 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2909 if (rtlight->currentcubemap != r_texture_whitecube)
2910 permutation |= SHADERPERMUTATION_CUBEFILTER;
2911 if (diffusescale > 0)
2912 permutation |= SHADERPERMUTATION_DIFFUSE;
2913 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2914 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2915 if (r_shadow_usingshadowmap2d)
2917 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2918 if (r_shadow_shadowmapvsdct)
2919 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2921 if (r_shadow_shadowmapsampler)
2922 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2923 if (r_shadow_shadowmappcf > 1)
2924 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2925 else if (r_shadow_shadowmappcf)
2926 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2928 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2929 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2930 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2931 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2932 switch(vid.renderpath)
2934 case RENDERPATH_D3D9:
2936 R_SetupShader_SetPermutationHLSL(mode, permutation);
2937 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2938 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2939 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2940 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2941 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2942 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2943 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2944 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2945 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2946 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2948 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2949 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2950 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2951 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2952 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2953 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2956 case RENDERPATH_D3D10:
2957 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2959 case RENDERPATH_D3D11:
2960 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2962 case RENDERPATH_GL20:
2963 case RENDERPATH_GLES2:
2964 R_SetupShader_SetPermutationGLSL(mode, permutation);
2965 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2966 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2967 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);
2968 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);
2969 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);
2970 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]);
2971 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]);
2972 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));
2973 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]);
2974 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2976 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2977 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2978 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2979 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2980 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2981 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2983 case RENDERPATH_GL11:
2984 case RENDERPATH_GL13:
2985 case RENDERPATH_GLES1:
2987 case RENDERPATH_SOFT:
2988 R_SetupShader_SetPermutationGLSL(mode, permutation);
2989 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2990 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2991 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2992 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2993 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2994 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2995 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]);
2996 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));
2997 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2998 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3000 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3001 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3002 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3003 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3004 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3005 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3010 #define SKINFRAME_HASH 1024
3014 int loadsequence; // incremented each level change
3015 memexpandablearray_t array;
3016 skinframe_t *hash[SKINFRAME_HASH];
3019 r_skinframe_t r_skinframe;
3021 void R_SkinFrame_PrepareForPurge(void)
3023 r_skinframe.loadsequence++;
3024 // wrap it without hitting zero
3025 if (r_skinframe.loadsequence >= 200)
3026 r_skinframe.loadsequence = 1;
3029 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3033 // mark the skinframe as used for the purging code
3034 skinframe->loadsequence = r_skinframe.loadsequence;
3037 void R_SkinFrame_Purge(void)
3041 for (i = 0;i < SKINFRAME_HASH;i++)
3043 for (s = r_skinframe.hash[i];s;s = s->next)
3045 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3047 if (s->merged == s->base)
3049 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3050 R_PurgeTexture(s->stain );s->stain = NULL;
3051 R_PurgeTexture(s->merged);s->merged = NULL;
3052 R_PurgeTexture(s->base );s->base = NULL;
3053 R_PurgeTexture(s->pants );s->pants = NULL;
3054 R_PurgeTexture(s->shirt );s->shirt = NULL;
3055 R_PurgeTexture(s->nmap );s->nmap = NULL;
3056 R_PurgeTexture(s->gloss );s->gloss = NULL;
3057 R_PurgeTexture(s->glow );s->glow = NULL;
3058 R_PurgeTexture(s->fog );s->fog = NULL;
3059 R_PurgeTexture(s->reflect);s->reflect = NULL;
3060 s->loadsequence = 0;
3066 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3068 char basename[MAX_QPATH];
3070 Image_StripImageExtension(name, basename, sizeof(basename));
3072 if( last == NULL ) {
3074 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3075 item = r_skinframe.hash[hashindex];
3080 // linearly search through the hash bucket
3081 for( ; item ; item = item->next ) {
3082 if( !strcmp( item->basename, basename ) ) {
3089 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3093 char basename[MAX_QPATH];
3095 Image_StripImageExtension(name, basename, sizeof(basename));
3097 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3098 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3099 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3103 rtexture_t *dyntexture;
3104 // check whether its a dynamic texture
3105 dyntexture = CL_GetDynTexture( basename );
3106 if (!add && !dyntexture)
3108 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3109 memset(item, 0, sizeof(*item));
3110 strlcpy(item->basename, basename, sizeof(item->basename));
3111 item->base = dyntexture; // either NULL or dyntexture handle
3112 item->textureflags = textureflags;
3113 item->comparewidth = comparewidth;
3114 item->compareheight = compareheight;
3115 item->comparecrc = comparecrc;
3116 item->next = r_skinframe.hash[hashindex];
3117 r_skinframe.hash[hashindex] = item;
3119 else if( item->base == NULL )
3121 rtexture_t *dyntexture;
3122 // check whether its a dynamic texture
3123 // 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]
3124 dyntexture = CL_GetDynTexture( basename );
3125 item->base = dyntexture; // either NULL or dyntexture handle
3128 R_SkinFrame_MarkUsed(item);
3132 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3134 unsigned long long avgcolor[5], wsum; \
3142 for(pix = 0; pix < cnt; ++pix) \
3145 for(comp = 0; comp < 3; ++comp) \
3147 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3150 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3152 for(comp = 0; comp < 3; ++comp) \
3153 avgcolor[comp] += getpixel * w; \
3156 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3157 avgcolor[4] += getpixel; \
3159 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3161 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3162 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3163 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3164 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3167 extern cvar_t gl_picmip;
3168 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3171 unsigned char *pixels;
3172 unsigned char *bumppixels;
3173 unsigned char *basepixels = NULL;
3174 int basepixels_width = 0;
3175 int basepixels_height = 0;
3176 skinframe_t *skinframe;
3177 rtexture_t *ddsbase = NULL;
3178 qboolean ddshasalpha = false;
3179 float ddsavgcolor[4];
3180 char basename[MAX_QPATH];
3181 int miplevel = R_PicmipForFlags(textureflags);
3182 int savemiplevel = miplevel;
3185 if (cls.state == ca_dedicated)
3188 // return an existing skinframe if already loaded
3189 // if loading of the first image fails, don't make a new skinframe as it
3190 // would cause all future lookups of this to be missing
3191 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3192 if (skinframe && skinframe->base)
3195 Image_StripImageExtension(name, basename, sizeof(basename));
3197 // check for DDS texture file first
3198 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3200 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3201 if (basepixels == NULL)
3205 // FIXME handle miplevel
3207 if (developer_loading.integer)
3208 Con_Printf("loading skin \"%s\"\n", name);
3210 // we've got some pixels to store, so really allocate this new texture now
3212 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3213 skinframe->stain = NULL;
3214 skinframe->merged = NULL;
3215 skinframe->base = NULL;
3216 skinframe->pants = NULL;
3217 skinframe->shirt = NULL;
3218 skinframe->nmap = NULL;
3219 skinframe->gloss = NULL;
3220 skinframe->glow = NULL;
3221 skinframe->fog = NULL;
3222 skinframe->reflect = NULL;
3223 skinframe->hasalpha = false;
3227 skinframe->base = ddsbase;
3228 skinframe->hasalpha = ddshasalpha;
3229 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3230 if (r_loadfog && skinframe->hasalpha)
3231 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3232 //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]);
3236 basepixels_width = image_width;
3237 basepixels_height = image_height;
3238 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3239 if (textureflags & TEXF_ALPHA)
3241 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3243 if (basepixels[j] < 255)
3245 skinframe->hasalpha = true;
3249 if (r_loadfog && skinframe->hasalpha)
3251 // has transparent pixels
3252 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3253 for (j = 0;j < image_width * image_height * 4;j += 4)
3258 pixels[j+3] = basepixels[j+3];
3260 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3264 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3265 //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]);
3266 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3267 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3268 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3269 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3274 mymiplevel = savemiplevel;
3275 if (r_loadnormalmap)
3276 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);
3277 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3279 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3280 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3281 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3282 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3285 // _norm is the name used by tenebrae and has been adopted as standard
3286 if (r_loadnormalmap && skinframe->nmap == NULL)
3288 mymiplevel = savemiplevel;
3289 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3291 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3295 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3297 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3298 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3299 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3301 Mem_Free(bumppixels);
3303 else if (r_shadow_bumpscale_basetexture.value > 0)
3305 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3306 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3307 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3310 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3311 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3314 // _luma is supported only for tenebrae compatibility
3315 // _glow is the preferred name
3316 mymiplevel = savemiplevel;
3317 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3319 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3320 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3321 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3322 Mem_Free(pixels);pixels = NULL;
3325 mymiplevel = savemiplevel;
3326 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3328 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3329 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3330 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3335 mymiplevel = savemiplevel;
3336 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3338 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3339 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3340 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3345 mymiplevel = savemiplevel;
3346 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3348 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3349 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3350 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3355 mymiplevel = savemiplevel;
3356 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3358 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3359 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3360 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3366 Mem_Free(basepixels);
3371 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3372 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3375 unsigned char *temp1, *temp2;
3376 skinframe_t *skinframe;
3378 if (cls.state == ca_dedicated)
3381 // if already loaded just return it, otherwise make a new skinframe
3382 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3383 if (skinframe && skinframe->base)
3386 skinframe->stain = NULL;
3387 skinframe->merged = NULL;
3388 skinframe->base = NULL;
3389 skinframe->pants = NULL;
3390 skinframe->shirt = NULL;
3391 skinframe->nmap = NULL;
3392 skinframe->gloss = NULL;
3393 skinframe->glow = NULL;
3394 skinframe->fog = NULL;
3395 skinframe->reflect = NULL;
3396 skinframe->hasalpha = false;
3398 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3402 if (developer_loading.integer)
3403 Con_Printf("loading 32bit skin \"%s\"\n", name);
3405 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3407 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3408 temp2 = temp1 + width * height * 4;
3409 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3410 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);
3413 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3414 if (textureflags & TEXF_ALPHA)
3416 for (i = 3;i < width * height * 4;i += 4)
3418 if (skindata[i] < 255)
3420 skinframe->hasalpha = true;
3424 if (r_loadfog && skinframe->hasalpha)
3426 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3427 memcpy(fogpixels, skindata, width * height * 4);
3428 for (i = 0;i < width * height * 4;i += 4)
3429 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3430 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3431 Mem_Free(fogpixels);
3435 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3436 //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]);
3441 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3445 skinframe_t *skinframe;
3447 if (cls.state == ca_dedicated)
3450 // if already loaded just return it, otherwise make a new skinframe
3451 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3452 if (skinframe && skinframe->base)
3455 skinframe->stain = NULL;
3456 skinframe->merged = NULL;
3457 skinframe->base = NULL;
3458 skinframe->pants = NULL;
3459 skinframe->shirt = NULL;
3460 skinframe->nmap = NULL;
3461 skinframe->gloss = NULL;
3462 skinframe->glow = NULL;
3463 skinframe->fog = NULL;
3464 skinframe->reflect = NULL;
3465 skinframe->hasalpha = false;
3467 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3471 if (developer_loading.integer)
3472 Con_Printf("loading quake skin \"%s\"\n", name);
3474 // 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)
3475 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3476 memcpy(skinframe->qpixels, skindata, width*height);
3477 skinframe->qwidth = width;
3478 skinframe->qheight = height;
3481 for (i = 0;i < width * height;i++)
3482 featuresmask |= palette_featureflags[skindata[i]];
3484 skinframe->hasalpha = false;
3485 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3486 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3487 skinframe->qgeneratemerged = true;
3488 skinframe->qgeneratebase = skinframe->qhascolormapping;
3489 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3491 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3492 //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]);
3497 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3501 unsigned char *skindata;
3503 if (!skinframe->qpixels)
3506 if (!skinframe->qhascolormapping)
3507 colormapped = false;
3511 if (!skinframe->qgeneratebase)
3516 if (!skinframe->qgeneratemerged)
3520 width = skinframe->qwidth;
3521 height = skinframe->qheight;
3522 skindata = skinframe->qpixels;
3524 if (skinframe->qgeneratenmap)
3526 unsigned char *temp1, *temp2;
3527 skinframe->qgeneratenmap = false;
3528 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3529 temp2 = temp1 + width * height * 4;
3530 // use either a custom palette or the quake palette
3531 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3532 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3533 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);
3537 if (skinframe->qgenerateglow)
3539 skinframe->qgenerateglow = false;
3540 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3545 skinframe->qgeneratebase = false;
3546 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);
3547 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3548 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3552 skinframe->qgeneratemerged = false;
3553 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);
3556 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3558 Mem_Free(skinframe->qpixels);
3559 skinframe->qpixels = NULL;
3563 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)
3566 skinframe_t *skinframe;
3568 if (cls.state == ca_dedicated)
3571 // if already loaded just return it, otherwise make a new skinframe
3572 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3573 if (skinframe && skinframe->base)
3576 skinframe->stain = NULL;
3577 skinframe->merged = NULL;
3578 skinframe->base = NULL;
3579 skinframe->pants = NULL;
3580 skinframe->shirt = NULL;
3581 skinframe->nmap = NULL;
3582 skinframe->gloss = NULL;
3583 skinframe->glow = NULL;
3584 skinframe->fog = NULL;
3585 skinframe->reflect = NULL;
3586 skinframe->hasalpha = false;
3588 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3592 if (developer_loading.integer)
3593 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3595 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3596 if (textureflags & TEXF_ALPHA)
3598 for (i = 0;i < width * height;i++)
3600 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3602 skinframe->hasalpha = true;
3606 if (r_loadfog && skinframe->hasalpha)
3607 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3610 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3611 //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]);
3616 skinframe_t *R_SkinFrame_LoadMissing(void)
3618 skinframe_t *skinframe;
3620 if (cls.state == ca_dedicated)
3623 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3624 skinframe->stain = NULL;
3625 skinframe->merged = NULL;
3626 skinframe->base = NULL;
3627 skinframe->pants = NULL;
3628 skinframe->shirt = NULL;
3629 skinframe->nmap = NULL;
3630 skinframe->gloss = NULL;
3631 skinframe->glow = NULL;
3632 skinframe->fog = NULL;
3633 skinframe->reflect = NULL;
3634 skinframe->hasalpha = false;
3636 skinframe->avgcolor[0] = rand() / RAND_MAX;
3637 skinframe->avgcolor[1] = rand() / RAND_MAX;
3638 skinframe->avgcolor[2] = rand() / RAND_MAX;
3639 skinframe->avgcolor[3] = 1;
3644 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3645 typedef struct suffixinfo_s
3648 qboolean flipx, flipy, flipdiagonal;
3651 static suffixinfo_t suffix[3][6] =
3654 {"px", false, false, false},
3655 {"nx", false, false, false},
3656 {"py", false, false, false},
3657 {"ny", false, false, false},
3658 {"pz", false, false, false},
3659 {"nz", false, false, false}
3662 {"posx", false, false, false},
3663 {"negx", false, false, false},
3664 {"posy", false, false, false},
3665 {"negy", false, false, false},
3666 {"posz", false, false, false},
3667 {"negz", false, false, false}
3670 {"rt", true, false, true},
3671 {"lf", false, true, true},
3672 {"ft", true, true, false},
3673 {"bk", false, false, false},
3674 {"up", true, false, true},
3675 {"dn", true, false, true}
3679 static int componentorder[4] = {0, 1, 2, 3};
3681 rtexture_t *R_LoadCubemap(const char *basename)
3683 int i, j, cubemapsize;
3684 unsigned char *cubemappixels, *image_buffer;
3685 rtexture_t *cubemaptexture;
3687 // must start 0 so the first loadimagepixels has no requested width/height
3689 cubemappixels = NULL;
3690 cubemaptexture = NULL;
3691 // keep trying different suffix groups (posx, px, rt) until one loads
3692 for (j = 0;j < 3 && !cubemappixels;j++)
3694 // load the 6 images in the suffix group
3695 for (i = 0;i < 6;i++)
3697 // generate an image name based on the base and and suffix
3698 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3700 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3702 // an image loaded, make sure width and height are equal
3703 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3705 // if this is the first image to load successfully, allocate the cubemap memory
3706 if (!cubemappixels && image_width >= 1)
3708 cubemapsize = image_width;
3709 // note this clears to black, so unavailable sides are black
3710 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3712 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3714 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);
3717 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3719 Mem_Free(image_buffer);
3723 // if a cubemap loaded, upload it
3726 if (developer_loading.integer)
3727 Con_Printf("loading cubemap \"%s\"\n", basename);
3729 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3730 Mem_Free(cubemappixels);
3734 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3735 if (developer_loading.integer)
3737 Con_Printf("(tried tried images ");
3738 for (j = 0;j < 3;j++)
3739 for (i = 0;i < 6;i++)
3740 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3741 Con_Print(" and was unable to find any of them).\n");
3744 return cubemaptexture;
3747 rtexture_t *R_GetCubemap(const char *basename)
3750 for (i = 0;i < r_texture_numcubemaps;i++)
3751 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3752 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3753 if (i >= MAX_CUBEMAPS)
3754 return r_texture_whitecube;
3755 r_texture_numcubemaps++;
3756 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3757 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3758 return r_texture_cubemaps[i].texture;
3761 void R_FreeCubemaps(void)
3764 for (i = 0;i < r_texture_numcubemaps;i++)
3766 if (developer_loading.integer)
3767 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3768 if (r_texture_cubemaps[i].texture)
3769 R_FreeTexture(r_texture_cubemaps[i].texture);
3771 r_texture_numcubemaps = 0;
3774 void R_Main_FreeViewCache(void)
3776 if (r_refdef.viewcache.entityvisible)
3777 Mem_Free(r_refdef.viewcache.entityvisible);
3778 if (r_refdef.viewcache.world_pvsbits)
3779 Mem_Free(r_refdef.viewcache.world_pvsbits);
3780 if (r_refdef.viewcache.world_leafvisible)
3781 Mem_Free(r_refdef.viewcache.world_leafvisible);
3782 if (r_refdef.viewcache.world_surfacevisible)
3783 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3784 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3787 void R_Main_ResizeViewCache(void)
3789 int numentities = r_refdef.scene.numentities;
3790 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3791 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3792 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3793 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3794 if (r_refdef.viewcache.maxentities < numentities)
3796 r_refdef.viewcache.maxentities = numentities;
3797 if (r_refdef.viewcache.entityvisible)
3798 Mem_Free(r_refdef.viewcache.entityvisible);
3799 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3801 if (r_refdef.viewcache.world_numclusters != numclusters)
3803 r_refdef.viewcache.world_numclusters = numclusters;
3804 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3805 if (r_refdef.viewcache.world_pvsbits)
3806 Mem_Free(r_refdef.viewcache.world_pvsbits);
3807 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3809 if (r_refdef.viewcache.world_numleafs != numleafs)
3811 r_refdef.viewcache.world_numleafs = numleafs;
3812 if (r_refdef.viewcache.world_leafvisible)
3813 Mem_Free(r_refdef.viewcache.world_leafvisible);
3814 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3816 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3818 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3819 if (r_refdef.viewcache.world_surfacevisible)
3820 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3821 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3825 extern rtexture_t *loadingscreentexture;
3826 void gl_main_start(void)
3828 loadingscreentexture = NULL;
3829 r_texture_blanknormalmap = NULL;
3830 r_texture_white = NULL;
3831 r_texture_grey128 = NULL;
3832 r_texture_black = NULL;
3833 r_texture_whitecube = NULL;
3834 r_texture_normalizationcube = NULL;
3835 r_texture_fogattenuation = NULL;
3836 r_texture_fogheighttexture = NULL;
3837 r_texture_gammaramps = NULL;
3838 r_texture_numcubemaps = 0;
3840 r_loaddds = r_texture_dds_load.integer != 0;
3841 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3843 switch(vid.renderpath)
3845 case RENDERPATH_GL20:
3846 case RENDERPATH_D3D9:
3847 case RENDERPATH_D3D10:
3848 case RENDERPATH_D3D11:
3849 case RENDERPATH_SOFT:
3850 case RENDERPATH_GLES2:
3851 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3852 Cvar_SetValueQuick(&gl_combine, 1);
3853 Cvar_SetValueQuick(&r_glsl, 1);
3854 r_loadnormalmap = true;
3858 case RENDERPATH_GL13:
3859 case RENDERPATH_GLES1:
3860 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3861 Cvar_SetValueQuick(&gl_combine, 1);
3862 Cvar_SetValueQuick(&r_glsl, 0);
3863 r_loadnormalmap = false;
3864 r_loadgloss = false;
3867 case RENDERPATH_GL11:
3868 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3869 Cvar_SetValueQuick(&gl_combine, 0);
3870 Cvar_SetValueQuick(&r_glsl, 0);
3871 r_loadnormalmap = false;
3872 r_loadgloss = false;
3878 R_FrameData_Reset();
3882 memset(r_queries, 0, sizeof(r_queries));
3884 r_qwskincache = NULL;
3885 r_qwskincache_size = 0;
3887 // due to caching of texture_t references, the collision cache must be reset
3888 Collision_Cache_Reset(true);
3890 // set up r_skinframe loading system for textures
3891 memset(&r_skinframe, 0, sizeof(r_skinframe));
3892 r_skinframe.loadsequence = 1;
3893 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3895 r_main_texturepool = R_AllocTexturePool();
3896 R_BuildBlankTextures();
3898 if (vid.support.arb_texture_cube_map)
3901 R_BuildNormalizationCube();
3903 r_texture_fogattenuation = NULL;
3904 r_texture_fogheighttexture = NULL;
3905 r_texture_gammaramps = NULL;
3906 //r_texture_fogintensity = NULL;
3907 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3908 memset(&r_waterstate, 0, sizeof(r_waterstate));
3909 r_glsl_permutation = NULL;
3910 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3911 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3912 glslshaderstring = NULL;
3914 r_hlsl_permutation = NULL;
3915 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3916 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3918 hlslshaderstring = NULL;
3919 memset(&r_svbsp, 0, sizeof (r_svbsp));
3921 r_refdef.fogmasktable_density = 0;
3924 void gl_main_shutdown(void)
3927 R_FrameData_Reset();
3929 R_Main_FreeViewCache();
3931 switch(vid.renderpath)
3933 case RENDERPATH_GL11:
3934 case RENDERPATH_GL13:
3935 case RENDERPATH_GL20:
3936 case RENDERPATH_GLES1:
3937 case RENDERPATH_GLES2:
3939 qglDeleteQueriesARB(r_maxqueries, r_queries);
3941 case RENDERPATH_D3D9:
3942 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3944 case RENDERPATH_D3D10:
3945 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3947 case RENDERPATH_D3D11:
3948 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3950 case RENDERPATH_SOFT:
3956 memset(r_queries, 0, sizeof(r_queries));
3958 r_qwskincache = NULL;
3959 r_qwskincache_size = 0;
3961 // clear out the r_skinframe state
3962 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3963 memset(&r_skinframe, 0, sizeof(r_skinframe));
3966 Mem_Free(r_svbsp.nodes);
3967 memset(&r_svbsp, 0, sizeof (r_svbsp));
3968 R_FreeTexturePool(&r_main_texturepool);
3969 loadingscreentexture = NULL;
3970 r_texture_blanknormalmap = NULL;
3971 r_texture_white = NULL;
3972 r_texture_grey128 = NULL;
3973 r_texture_black = NULL;
3974 r_texture_whitecube = NULL;
3975 r_texture_normalizationcube = NULL;
3976 r_texture_fogattenuation = NULL;
3977 r_texture_fogheighttexture = NULL;
3978 r_texture_gammaramps = NULL;
3979 r_texture_numcubemaps = 0;
3980 //r_texture_fogintensity = NULL;
3981 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3982 memset(&r_waterstate, 0, sizeof(r_waterstate));
3985 r_glsl_permutation = NULL;
3986 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3987 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3988 glslshaderstring = NULL;
3990 r_hlsl_permutation = NULL;
3991 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3992 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3994 hlslshaderstring = NULL;
3997 extern void CL_ParseEntityLump(char *entitystring);
3998 void gl_main_newmap(void)
4000 // FIXME: move this code to client
4001 char *entities, entname[MAX_QPATH];
4003 Mem_Free(r_qwskincache);
4004 r_qwskincache = NULL;
4005 r_qwskincache_size = 0;
4008 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4009 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4011 CL_ParseEntityLump(entities);
4015 if (cl.worldmodel->brush.entities)
4016 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4018 R_Main_FreeViewCache();
4020 R_FrameData_Reset();
4023 void GL_Main_Init(void)
4025 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4027 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4028 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4029 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4030 if (gamemode == GAME_NEHAHRA)
4032 Cvar_RegisterVariable (&gl_fogenable);
4033 Cvar_RegisterVariable (&gl_fogdensity);
4034 Cvar_RegisterVariable (&gl_fogred);
4035 Cvar_RegisterVariable (&gl_foggreen);
4036 Cvar_RegisterVariable (&gl_fogblue);
4037 Cvar_RegisterVariable (&gl_fogstart);
4038 Cvar_RegisterVariable (&gl_fogend);
4039 Cvar_RegisterVariable (&gl_skyclip);
4041 Cvar_RegisterVariable(&r_motionblur);
4042 Cvar_RegisterVariable(&r_motionblur_maxblur);
4043 Cvar_RegisterVariable(&r_motionblur_bmin);
4044 Cvar_RegisterVariable(&r_motionblur_vmin);
4045 Cvar_RegisterVariable(&r_motionblur_vmax);
4046 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4047 Cvar_RegisterVariable(&r_motionblur_randomize);
4048 Cvar_RegisterVariable(&r_damageblur);
4049 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4050 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4051 Cvar_RegisterVariable(&r_equalize_entities_by);
4052 Cvar_RegisterVariable(&r_equalize_entities_to);
4053 Cvar_RegisterVariable(&r_depthfirst);
4054 Cvar_RegisterVariable(&r_useinfinitefarclip);
4055 Cvar_RegisterVariable(&r_farclip_base);
4056 Cvar_RegisterVariable(&r_farclip_world);
4057 Cvar_RegisterVariable(&r_nearclip);
4058 Cvar_RegisterVariable(&r_deformvertexes);
4059 Cvar_RegisterVariable(&r_transparent);
4060 Cvar_RegisterVariable(&r_showoverdraw);
4061 Cvar_RegisterVariable(&r_showbboxes);
4062 Cvar_RegisterVariable(&r_showsurfaces);
4063 Cvar_RegisterVariable(&r_showtris);
4064 Cvar_RegisterVariable(&r_shownormals);
4065 Cvar_RegisterVariable(&r_showlighting);
4066 Cvar_RegisterVariable(&r_showshadowvolumes);
4067 Cvar_RegisterVariable(&r_showcollisionbrushes);
4068 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4069 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4070 Cvar_RegisterVariable(&r_showdisabledepthtest);
4071 Cvar_RegisterVariable(&r_drawportals);
4072 Cvar_RegisterVariable(&r_drawentities);
4073 Cvar_RegisterVariable(&r_draw2d);
4074 Cvar_RegisterVariable(&r_drawworld);
4075 Cvar_RegisterVariable(&r_cullentities_trace);
4076 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4077 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4078 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4079 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4080 Cvar_RegisterVariable(&r_drawviewmodel);
4081 Cvar_RegisterVariable(&r_drawexteriormodel);
4082 Cvar_RegisterVariable(&r_speeds);
4083 Cvar_RegisterVariable(&r_fullbrights);
4084 Cvar_RegisterVariable(&r_wateralpha);
4085 Cvar_RegisterVariable(&r_dynamic);
4086 Cvar_RegisterVariable(&r_fakelight);
4087 Cvar_RegisterVariable(&r_fakelight_intensity);
4088 Cvar_RegisterVariable(&r_fullbright);
4089 Cvar_RegisterVariable(&r_shadows);
4090 Cvar_RegisterVariable(&r_shadows_darken);
4091 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4092 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4093 Cvar_RegisterVariable(&r_shadows_throwdistance);
4094 Cvar_RegisterVariable(&r_shadows_throwdirection);
4095 Cvar_RegisterVariable(&r_shadows_focus);
4096 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4097 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4098 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4099 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4100 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4101 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4102 Cvar_RegisterVariable(&r_fog_exp2);
4103 Cvar_RegisterVariable(&r_fog_clear);
4104 Cvar_RegisterVariable(&r_drawfog);
4105 Cvar_RegisterVariable(&r_transparentdepthmasking);
4106 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4107 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4108 Cvar_RegisterVariable(&r_texture_dds_load);
4109 Cvar_RegisterVariable(&r_texture_dds_save);
4110 Cvar_RegisterVariable(&r_texture_sRGB_2d);
4111 Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4112 Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4113 Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4114 Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4115 Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4116 Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4117 Cvar_RegisterVariable(&r_textureunits);
4118 Cvar_RegisterVariable(&gl_combine);
4119 Cvar_RegisterVariable(&r_viewfbo);
4120 Cvar_RegisterVariable(&r_viewscale);
4121 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4122 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4123 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4124 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4125 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4126 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4127 Cvar_RegisterVariable(&r_glsl);
4128 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4129 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4130 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4131 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4132 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4133 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4134 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4135 Cvar_RegisterVariable(&r_glsl_postprocess);
4136 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4137 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4138 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4139 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4140 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4141 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4142 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4143 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4145 Cvar_RegisterVariable(&r_water);
4146 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4147 Cvar_RegisterVariable(&r_water_clippingplanebias);
4148 Cvar_RegisterVariable(&r_water_refractdistort);
4149 Cvar_RegisterVariable(&r_water_reflectdistort);
4150 Cvar_RegisterVariable(&r_water_scissormode);
4151 Cvar_RegisterVariable(&r_lerpsprites);
4152 Cvar_RegisterVariable(&r_lerpmodels);
4153 Cvar_RegisterVariable(&r_lerplightstyles);
4154 Cvar_RegisterVariable(&r_waterscroll);
4155 Cvar_RegisterVariable(&r_bloom);
4156 Cvar_RegisterVariable(&r_bloom_colorscale);
4157 Cvar_RegisterVariable(&r_bloom_brighten);
4158 Cvar_RegisterVariable(&r_bloom_blur);
4159 Cvar_RegisterVariable(&r_bloom_resolution);
4160 Cvar_RegisterVariable(&r_bloom_colorexponent);
4161 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4162 Cvar_RegisterVariable(&r_hdr);
4163 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4164 Cvar_RegisterVariable(&r_hdr_glowintensity);
4165 Cvar_RegisterVariable(&r_hdr_range);
4166 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4167 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4168 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4169 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4170 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4171 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4172 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4173 Cvar_RegisterVariable(&developer_texturelogging);
4174 Cvar_RegisterVariable(&gl_lightmaps);
4175 Cvar_RegisterVariable(&r_test);
4176 Cvar_RegisterVariable(&r_glsl_saturation);
4177 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4178 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4179 Cvar_RegisterVariable(&r_framedatasize);
4180 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4181 Cvar_SetValue("r_fullbrights", 0);
4182 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4184 Cvar_RegisterVariable(&r_track_sprites);
4185 Cvar_RegisterVariable(&r_track_sprites_flags);
4186 Cvar_RegisterVariable(&r_track_sprites_scalew);
4187 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4188 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4189 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4190 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4191 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4194 extern void R_Textures_Init(void);
4195 extern void GL_Draw_Init(void);
4196 extern void GL_Main_Init(void);
4197 extern void R_Shadow_Init(void);
4198 extern void R_Sky_Init(void);
4199 extern void GL_Surf_Init(void);
4200 extern void R_Particles_Init(void);
4201 extern void R_Explosion_Init(void);
4202 extern void gl_backend_init(void);
4203 extern void Sbar_Init(void);
4204 extern void R_LightningBeams_Init(void);
4205 extern void Mod_RenderInit(void);
4206 extern void Font_Init(void);
4208 void Render_Init(void)
4221 R_LightningBeams_Init();
4230 extern char *ENGINE_EXTENSIONS;
4233 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4234 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4235 gl_version = (const char *)qglGetString(GL_VERSION);
4236 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4240 if (!gl_platformextensions)
4241 gl_platformextensions = "";
4243 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4244 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4245 Con_Printf("GL_VERSION: %s\n", gl_version);
4246 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4247 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4249 VID_CheckExtensions();
4251 // LordHavoc: report supported extensions
4252 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4254 // clear to black (loading plaque will be seen over this)
4255 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4258 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4262 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4264 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4267 p = r_refdef.view.frustum + i;
4272 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4276 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4280 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4284 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4288 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4292 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4296 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4300 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4308 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4312 for (i = 0;i < numplanes;i++)
4319 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4323 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4327 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4331 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4335 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4339 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4343 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4347 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4355 //==================================================================================
4357 // LordHavoc: this stores temporary data used within the same frame
4359 typedef struct r_framedata_mem_s
4361 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4362 size_t size; // how much usable space
4363 size_t current; // how much space in use
4364 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4365 size_t wantedsize; // how much space was allocated
4366 unsigned char *data; // start of real data (16byte aligned)
4370 static r_framedata_mem_t *r_framedata_mem;
4372 void R_FrameData_Reset(void)
4374 while (r_framedata_mem)
4376 r_framedata_mem_t *next = r_framedata_mem->purge;
4377 Mem_Free(r_framedata_mem);
4378 r_framedata_mem = next;
4382 void R_FrameData_Resize(void)
4385 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4386 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4387 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4389 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4390 newmem->wantedsize = wantedsize;
4391 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4392 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4393 newmem->current = 0;
4395 newmem->purge = r_framedata_mem;
4396 r_framedata_mem = newmem;
4400 void R_FrameData_NewFrame(void)
4402 R_FrameData_Resize();
4403 if (!r_framedata_mem)
4405 // if we ran out of space on the last frame, free the old memory now
4406 while (r_framedata_mem->purge)
4408 // repeatedly remove the second item in the list, leaving only head
4409 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4410 Mem_Free(r_framedata_mem->purge);
4411 r_framedata_mem->purge = next;
4413 // reset the current mem pointer
4414 r_framedata_mem->current = 0;
4415 r_framedata_mem->mark = 0;
4418 void *R_FrameData_Alloc(size_t size)
4422 // align to 16 byte boundary - the data pointer is already aligned, so we
4423 // only need to ensure the size of every allocation is also aligned
4424 size = (size + 15) & ~15;
4426 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4428 // emergency - we ran out of space, allocate more memory
4429 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4430 R_FrameData_Resize();
4433 data = r_framedata_mem->data + r_framedata_mem->current;
4434 r_framedata_mem->current += size;
4436 // count the usage for stats
4437 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4438 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4440 return (void *)data;
4443 void *R_FrameData_Store(size_t size, void *data)
4445 void *d = R_FrameData_Alloc(size);
4447 memcpy(d, data, size);
4451 void R_FrameData_SetMark(void)
4453 if (!r_framedata_mem)
4455 r_framedata_mem->mark = r_framedata_mem->current;
4458 void R_FrameData_ReturnToMark(void)
4460 if (!r_framedata_mem)
4462 r_framedata_mem->current = r_framedata_mem->mark;
4465 //==================================================================================
4467 // LordHavoc: animcache originally written by Echon, rewritten since then
4470 * Animation cache prevents re-generating mesh data for an animated model
4471 * multiple times in one frame for lighting, shadowing, reflections, etc.
4474 void R_AnimCache_Free(void)
4478 void R_AnimCache_ClearCache(void)
4481 entity_render_t *ent;
4483 for (i = 0;i < r_refdef.scene.numentities;i++)
4485 ent = r_refdef.scene.entities[i];
4486 ent->animcache_vertex3f = NULL;
4487 ent->animcache_normal3f = NULL;
4488 ent->animcache_svector3f = NULL;
4489 ent->animcache_tvector3f = NULL;
4490 ent->animcache_vertexmesh = NULL;
4491 ent->animcache_vertex3fbuffer = NULL;
4492 ent->animcache_vertexmeshbuffer = NULL;
4496 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4500 // check if we need the meshbuffers
4501 if (!vid.useinterleavedarrays)
4504 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4505 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4506 // TODO: upload vertex3f buffer?
4507 if (ent->animcache_vertexmesh)
4509 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4510 for (i = 0;i < numvertices;i++)
4511 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4512 if (ent->animcache_svector3f)
4513 for (i = 0;i < numvertices;i++)
4514 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4515 if (ent->animcache_tvector3f)
4516 for (i = 0;i < numvertices;i++)
4517 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4518 if (ent->animcache_normal3f)
4519 for (i = 0;i < numvertices;i++)
4520 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4521 // TODO: upload vertexmeshbuffer?
4525 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4527 dp_model_t *model = ent->model;
4529 // see if it's already cached this frame
4530 if (ent->animcache_vertex3f)
4532 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4533 if (wantnormals || wanttangents)
4535 if (ent->animcache_normal3f)
4536 wantnormals = false;
4537 if (ent->animcache_svector3f)
4538 wanttangents = false;
4539 if (wantnormals || wanttangents)
4541 numvertices = model->surfmesh.num_vertices;
4543 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4550 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4556 // see if this ent is worth caching
4557 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4559 // get some memory for this entity and generate mesh data
4560 numvertices = model->surfmesh.num_vertices;
4561 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4563 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4566 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4567 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4569 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4570 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4575 void R_AnimCache_CacheVisibleEntities(void)
4578 qboolean wantnormals = true;
4579 qboolean wanttangents = !r_showsurfaces.integer;
4581 switch(vid.renderpath)
4583 case RENDERPATH_GL20:
4584 case RENDERPATH_D3D9:
4585 case RENDERPATH_D3D10:
4586 case RENDERPATH_D3D11:
4587 case RENDERPATH_GLES2:
4589 case RENDERPATH_GL11:
4590 case RENDERPATH_GL13:
4591 case RENDERPATH_GLES1:
4592 wanttangents = false;
4594 case RENDERPATH_SOFT:
4598 if (r_shownormals.integer)
4599 wanttangents = wantnormals = true;
4601 // TODO: thread this
4602 // NOTE: R_PrepareRTLights() also caches entities
4604 for (i = 0;i < r_refdef.scene.numentities;i++)
4605 if (r_refdef.viewcache.entityvisible[i])
4606 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4609 //==================================================================================
4611 static void R_View_UpdateEntityLighting (void)
4614 entity_render_t *ent;
4615 vec3_t tempdiffusenormal, avg;
4616 vec_t f, fa, fd, fdd;
4617 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4619 for (i = 0;i < r_refdef.scene.numentities;i++)
4621 ent = r_refdef.scene.entities[i];
4623 // skip unseen models
4624 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4628 if (ent->model && ent->model->brush.num_leafs)
4630 // TODO: use modellight for r_ambient settings on world?
4631 VectorSet(ent->modellight_ambient, 0, 0, 0);
4632 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4633 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4637 // fetch the lighting from the worldmodel data
4638 VectorClear(ent->modellight_ambient);
4639 VectorClear(ent->modellight_diffuse);
4640 VectorClear(tempdiffusenormal);
4641 if (ent->flags & RENDER_LIGHT)
4644 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4646 // complete lightning for lit sprites
4647 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4648 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4650 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4651 org[2] = org[2] + r_overheadsprites_pushback.value;
4652 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4655 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4657 if(ent->flags & RENDER_EQUALIZE)
4659 // first fix up ambient lighting...
4660 if(r_equalize_entities_minambient.value > 0)
4662 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4665 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4666 if(fa < r_equalize_entities_minambient.value * fd)
4669 // fa'/fd' = minambient
4670 // fa'+0.25*fd' = fa+0.25*fd
4672 // fa' = fd' * minambient
4673 // fd'*(0.25+minambient) = fa+0.25*fd
4675 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4676 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4678 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4679 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
4680 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4681 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4686 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4688 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4689 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4693 // adjust brightness and saturation to target
4694 avg[0] = avg[1] = avg[2] = fa / f;
4695 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4696 avg[0] = avg[1] = avg[2] = fd / f;
4697 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4703 VectorSet(ent->modellight_ambient, 1, 1, 1);
4705 // move the light direction into modelspace coordinates for lighting code
4706 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4707 if(VectorLength2(ent->modellight_lightdir) == 0)
4708 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4709 VectorNormalize(ent->modellight_lightdir);
4713 #define MAX_LINEOFSIGHTTRACES 64
4715 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4718 vec3_t boxmins, boxmaxs;
4721 dp_model_t *model = r_refdef.scene.worldmodel;
4723 if (!model || !model->brush.TraceLineOfSight)
4726 // expand the box a little
4727 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4728 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4729 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4730 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4731 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4732 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4734 // return true if eye is inside enlarged box
4735 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4739 VectorCopy(eye, start);
4740 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4741 if (model->brush.TraceLineOfSight(model, start, end))
4744 // try various random positions
4745 for (i = 0;i < numsamples;i++)
4747 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4748 if (model->brush.TraceLineOfSight(model, start, end))
4756 static void R_View_UpdateEntityVisible (void)
4761 entity_render_t *ent;
4763 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4764 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4765 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4766 : RENDER_EXTERIORMODEL;
4767 if (!r_drawviewmodel.integer)
4768 renderimask |= RENDER_VIEWMODEL;
4769 if (!r_drawexteriormodel.integer)
4770 renderimask |= RENDER_EXTERIORMODEL;
4771 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4773 // worldmodel can check visibility
4774 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4775 for (i = 0;i < r_refdef.scene.numentities;i++)
4777 ent = r_refdef.scene.entities[i];
4778 if (!(ent->flags & renderimask))
4779 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)))
4780 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))
4781 r_refdef.viewcache.entityvisible[i] = true;
4786 // no worldmodel or it can't check visibility
4787 for (i = 0;i < r_refdef.scene.numentities;i++)
4789 ent = r_refdef.scene.entities[i];
4790 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));
4793 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4794 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4796 for (i = 0;i < r_refdef.scene.numentities;i++)
4798 if (!r_refdef.viewcache.entityvisible[i])
4800 ent = r_refdef.scene.entities[i];
4801 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4803 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4805 continue; // temp entities do pvs only
4806 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4807 ent->last_trace_visibility = realtime;
4808 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4809 r_refdef.viewcache.entityvisible[i] = 0;
4815 /// only used if skyrendermasked, and normally returns false
4816 int R_DrawBrushModelsSky (void)
4819 entity_render_t *ent;
4822 for (i = 0;i < r_refdef.scene.numentities;i++)
4824 if (!r_refdef.viewcache.entityvisible[i])
4826 ent = r_refdef.scene.entities[i];
4827 if (!ent->model || !ent->model->DrawSky)
4829 ent->model->DrawSky(ent);
4835 static void R_DrawNoModel(entity_render_t *ent);
4836 static void R_DrawModels(void)
4839 entity_render_t *ent;
4841 for (i = 0;i < r_refdef.scene.numentities;i++)
4843 if (!r_refdef.viewcache.entityvisible[i])
4845 ent = r_refdef.scene.entities[i];
4846 r_refdef.stats.entities++;
4848 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4851 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4852 Con_Printf("R_DrawModels\n");
4853 Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4854 Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4855 Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4858 if (ent->model && ent->model->Draw != NULL)
4859 ent->model->Draw(ent);
4865 static void R_DrawModelsDepth(void)
4868 entity_render_t *ent;
4870 for (i = 0;i < r_refdef.scene.numentities;i++)
4872 if (!r_refdef.viewcache.entityvisible[i])
4874 ent = r_refdef.scene.entities[i];
4875 if (ent->model && ent->model->DrawDepth != NULL)
4876 ent->model->DrawDepth(ent);
4880 static void R_DrawModelsDebug(void)
4883 entity_render_t *ent;
4885 for (i = 0;i < r_refdef.scene.numentities;i++)
4887 if (!r_refdef.viewcache.entityvisible[i])
4889 ent = r_refdef.scene.entities[i];
4890 if (ent->model && ent->model->DrawDebug != NULL)
4891 ent->model->DrawDebug(ent);
4895 static void R_DrawModelsAddWaterPlanes(void)
4898 entity_render_t *ent;
4900 for (i = 0;i < r_refdef.scene.numentities;i++)
4902 if (!r_refdef.viewcache.entityvisible[i])
4904 ent = r_refdef.scene.entities[i];
4905 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4906 ent->model->DrawAddWaterPlanes(ent);
4910 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4912 if (r_hdr_irisadaptation.integer)
4916 vec3_t diffusenormal;
4921 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4922 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4923 brightness = max(0.0000001f, brightness);
4924 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4925 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4926 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4927 current = r_hdr_irisadaptation_value.value;
4929 current = min(current + adjust, goal);
4930 else if (current > goal)
4931 current = max(current - adjust, goal);
4932 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4933 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4935 else if (r_hdr_irisadaptation_value.value != 1.0f)
4936 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4939 static void R_View_SetFrustum(const int *scissor)
4942 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4943 vec3_t forward, left, up, origin, v;
4947 // flipped x coordinates (because x points left here)
4948 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4949 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4951 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4952 switch(vid.renderpath)
4954 case RENDERPATH_D3D9:
4955 case RENDERPATH_D3D10:
4956 case RENDERPATH_D3D11:
4957 // non-flipped y coordinates
4958 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4959 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4961 case RENDERPATH_SOFT:
4962 case RENDERPATH_GL11:
4963 case RENDERPATH_GL13:
4964 case RENDERPATH_GL20:
4965 case RENDERPATH_GLES1:
4966 case RENDERPATH_GLES2:
4967 // non-flipped y coordinates
4968 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4969 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4974 // we can't trust r_refdef.view.forward and friends in reflected scenes
4975 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4978 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4979 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4980 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4981 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4982 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4983 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4984 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4985 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4986 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4987 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4988 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4989 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4993 zNear = r_refdef.nearclip;
4994 nudge = 1.0 - 1.0 / (1<<23);
4995 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4996 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4997 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4998 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4999 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5000 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5001 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5002 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5008 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5009 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5010 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5011 r_refdef.view.frustum[0].dist = m[15] - m[12];
5013 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5014 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5015 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5016 r_refdef.view.frustum[1].dist = m[15] + m[12];
5018 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5019 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5020 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5021 r_refdef.view.frustum[2].dist = m[15] - m[13];
5023 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5024 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5025 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5026 r_refdef.view.frustum[3].dist = m[15] + m[13];
5028 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5029 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5030 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5031 r_refdef.view.frustum[4].dist = m[15] - m[14];
5033 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5034 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5035 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5036 r_refdef.view.frustum[5].dist = m[15] + m[14];
5039 if (r_refdef.view.useperspective)
5041 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5042 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]);
5043 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]);
5044 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]);
5045 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]);
5047 // then the normals from the corners relative to origin
5048 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5049 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5050 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5051 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5053 // in a NORMAL view, forward cross left == up
5054 // in a REFLECTED view, forward cross left == down
5055 // so our cross products above need to be adjusted for a left handed coordinate system
5056 CrossProduct(forward, left, v);
5057 if(DotProduct(v, up) < 0)
5059 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5060 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5061 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5062 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5065 // Leaving those out was a mistake, those were in the old code, and they
5066 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5067 // I couldn't reproduce it after adding those normalizations. --blub
5068 VectorNormalize(r_refdef.view.frustum[0].normal);
5069 VectorNormalize(r_refdef.view.frustum[1].normal);
5070 VectorNormalize(r_refdef.view.frustum[2].normal);
5071 VectorNormalize(r_refdef.view.frustum[3].normal);
5073 // make the corners absolute
5074 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5075 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5076 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5077 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5080 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5082 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5083 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5084 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5085 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5086 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5090 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5091 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5092 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5093 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5094 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5095 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5096 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5097 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5098 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5099 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5101 r_refdef.view.numfrustumplanes = 5;
5103 if (r_refdef.view.useclipplane)
5105 r_refdef.view.numfrustumplanes = 6;
5106 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5109 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5110 PlaneClassify(r_refdef.view.frustum + i);
5112 // LordHavoc: note to all quake engine coders, Quake had a special case
5113 // for 90 degrees which assumed a square view (wrong), so I removed it,
5114 // Quake2 has it disabled as well.
5116 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5117 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5118 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5119 //PlaneClassify(&frustum[0]);
5121 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5122 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5123 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5124 //PlaneClassify(&frustum[1]);
5126 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5127 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5128 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5129 //PlaneClassify(&frustum[2]);
5131 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5132 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5133 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5134 //PlaneClassify(&frustum[3]);
5137 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5138 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5139 //PlaneClassify(&frustum[4]);
5142 void R_View_UpdateWithScissor(const int *myscissor)
5144 R_Main_ResizeViewCache();
5145 R_View_SetFrustum(myscissor);
5146 R_View_WorldVisibility(r_refdef.view.useclipplane);
5147 R_View_UpdateEntityVisible();
5148 R_View_UpdateEntityLighting();
5151 void R_View_Update(void)
5153 R_Main_ResizeViewCache();
5154 R_View_SetFrustum(NULL);
5155 R_View_WorldVisibility(r_refdef.view.useclipplane);
5156 R_View_UpdateEntityVisible();
5157 R_View_UpdateEntityLighting();
5160 float viewscalefpsadjusted = 1.0f;
5162 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5164 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5165 scale = bound(0.03125f, scale, 1.0f);
5166 *outwidth = (int)ceil(width * scale);
5167 *outheight = (int)ceil(height * scale);
5170 void R_Mesh_SetMainRenderTargets(void)
5172 if (r_bloomstate.fbo_framebuffer)
5173 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5175 R_Mesh_ResetRenderTargets();
5178 void R_SetupView(qboolean allowwaterclippingplane)
5180 const float *customclipplane = NULL;
5182 int scaledwidth, scaledheight;
5183 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5185 // LordHavoc: couldn't figure out how to make this approach the
5186 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5187 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5188 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5189 dist = r_refdef.view.clipplane.dist;
5190 plane[0] = r_refdef.view.clipplane.normal[0];
5191 plane[1] = r_refdef.view.clipplane.normal[1];
5192 plane[2] = r_refdef.view.clipplane.normal[2];
5194 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5197 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5198 if (!r_refdef.view.useperspective)
5199 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5200 else if (vid.stencil && r_useinfinitefarclip.integer)
5201 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5203 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5204 R_Mesh_SetMainRenderTargets();
5205 R_SetViewport(&r_refdef.view.viewport);
5206 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5208 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5209 float screenplane[4];
5210 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5211 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5212 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5213 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5214 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5218 void R_EntityMatrix(const matrix4x4_t *matrix)
5220 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5222 gl_modelmatrixchanged = false;
5223 gl_modelmatrix = *matrix;
5224 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5225 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5226 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5227 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5229 switch(vid.renderpath)
5231 case RENDERPATH_D3D9:
5233 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5234 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5237 case RENDERPATH_D3D10:
5238 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5240 case RENDERPATH_D3D11:
5241 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5243 case RENDERPATH_GL11:
5244 case RENDERPATH_GL13:
5245 case RENDERPATH_GLES1:
5246 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5248 case RENDERPATH_SOFT:
5249 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5250 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5252 case RENDERPATH_GL20:
5253 case RENDERPATH_GLES2:
5254 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5255 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5261 void R_ResetViewRendering2D(void)
5263 r_viewport_t viewport;
5266 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5267 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);
5268 R_Mesh_ResetRenderTargets();
5269 R_SetViewport(&viewport);
5270 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5271 GL_Color(1, 1, 1, 1);
5272 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5273 GL_BlendFunc(GL_ONE, GL_ZERO);
5274 GL_ScissorTest(false);
5275 GL_DepthMask(false);
5276 GL_DepthRange(0, 1);
5277 GL_DepthTest(false);
5278 GL_DepthFunc(GL_LEQUAL);
5279 R_EntityMatrix(&identitymatrix);
5280 R_Mesh_ResetTextureState();
5281 GL_PolygonOffset(0, 0);
5282 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5283 switch(vid.renderpath)
5285 case RENDERPATH_GL11:
5286 case RENDERPATH_GL13:
5287 case RENDERPATH_GL20:
5288 case RENDERPATH_GLES1:
5289 case RENDERPATH_GLES2:
5290 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5292 case RENDERPATH_D3D9:
5293 case RENDERPATH_D3D10:
5294 case RENDERPATH_D3D11:
5295 case RENDERPATH_SOFT:
5298 GL_CullFace(GL_NONE);
5301 void R_ResetViewRendering3D(void)
5306 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5307 GL_Color(1, 1, 1, 1);
5308 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5309 GL_BlendFunc(GL_ONE, GL_ZERO);
5310 GL_ScissorTest(true);
5312 GL_DepthRange(0, 1);
5314 GL_DepthFunc(GL_LEQUAL);
5315 R_EntityMatrix(&identitymatrix);
5316 R_Mesh_ResetTextureState();
5317 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5318 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5319 switch(vid.renderpath)
5321 case RENDERPATH_GL11:
5322 case RENDERPATH_GL13:
5323 case RENDERPATH_GL20:
5324 case RENDERPATH_GLES1:
5325 case RENDERPATH_GLES2:
5326 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5328 case RENDERPATH_D3D9:
5329 case RENDERPATH_D3D10:
5330 case RENDERPATH_D3D11:
5331 case RENDERPATH_SOFT:
5334 GL_CullFace(r_refdef.view.cullface_back);
5339 R_RenderView_UpdateViewVectors
5342 static void R_RenderView_UpdateViewVectors(void)
5344 // break apart the view matrix into vectors for various purposes
5345 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5346 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5347 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5348 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5349 // make an inverted copy of the view matrix for tracking sprites
5350 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5353 void R_RenderScene(void);
5354 void R_RenderWaterPlanes(void);
5356 static void R_Water_StartFrame(void)
5359 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5360 r_waterstate_waterplane_t *p;
5362 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5365 switch(vid.renderpath)
5367 case RENDERPATH_GL20:
5368 case RENDERPATH_D3D9:
5369 case RENDERPATH_D3D10:
5370 case RENDERPATH_D3D11:
5371 case RENDERPATH_SOFT:
5372 case RENDERPATH_GLES2:
5374 case RENDERPATH_GL11:
5375 case RENDERPATH_GL13:
5376 case RENDERPATH_GLES1:
5380 // set waterwidth and waterheight to the water resolution that will be
5381 // used (often less than the screen resolution for faster rendering)
5382 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5383 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5385 // calculate desired texture sizes
5386 // can't use water if the card does not support the texture size
5387 if (!r_water.integer || r_showsurfaces.integer)
5388 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5389 else if (vid.support.arb_texture_non_power_of_two)
5391 texturewidth = waterwidth;
5392 textureheight = waterheight;
5393 camerawidth = waterwidth;
5394 cameraheight = waterheight;
5398 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5399 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5400 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5401 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5404 // allocate textures as needed
5405 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5407 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5408 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5410 if (p->texture_refraction)
5411 R_FreeTexture(p->texture_refraction);
5412 p->texture_refraction = NULL;
5413 if (p->texture_reflection)
5414 R_FreeTexture(p->texture_reflection);
5415 p->texture_reflection = NULL;
5416 if (p->texture_camera)
5417 R_FreeTexture(p->texture_camera);
5418 p->texture_camera = NULL;
5420 memset(&r_waterstate, 0, sizeof(r_waterstate));
5421 r_waterstate.texturewidth = texturewidth;
5422 r_waterstate.textureheight = textureheight;
5423 r_waterstate.camerawidth = camerawidth;
5424 r_waterstate.cameraheight = cameraheight;
5427 if (r_waterstate.texturewidth)
5429 r_waterstate.enabled = true;
5431 // when doing a reduced render (HDR) we want to use a smaller area
5432 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5433 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5435 // set up variables that will be used in shader setup
5436 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5437 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5438 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5439 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5442 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5443 r_waterstate.numwaterplanes = 0;
5446 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5448 int triangleindex, planeindex;
5454 r_waterstate_waterplane_t *p;
5455 texture_t *t = R_GetCurrentTexture(surface->texture);
5457 // just use the first triangle with a valid normal for any decisions
5458 VectorClear(normal);
5459 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5461 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5462 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5463 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5464 TriangleNormal(vert[0], vert[1], vert[2], normal);
5465 if (VectorLength2(normal) >= 0.001)
5469 VectorCopy(normal, plane.normal);
5470 VectorNormalize(plane.normal);
5471 plane.dist = DotProduct(vert[0], plane.normal);
5472 PlaneClassify(&plane);
5473 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5475 // skip backfaces (except if nocullface is set)
5476 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5478 VectorNegate(plane.normal, plane.normal);
5480 PlaneClassify(&plane);
5484 // find a matching plane if there is one
5485 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5486 if(p->camera_entity == t->camera_entity)
5487 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5489 if (planeindex >= r_waterstate.maxwaterplanes)
5490 return; // nothing we can do, out of planes
5492 // if this triangle does not fit any known plane rendered this frame, add one
5493 if (planeindex >= r_waterstate.numwaterplanes)
5495 // store the new plane
5496 r_waterstate.numwaterplanes++;
5498 // clear materialflags and pvs
5499 p->materialflags = 0;
5500 p->pvsvalid = false;
5501 p->camera_entity = t->camera_entity;
5502 VectorCopy(surface->mins, p->mins);
5503 VectorCopy(surface->maxs, p->maxs);
5508 p->mins[0] = min(p->mins[0], surface->mins[0]);
5509 p->mins[1] = min(p->mins[1], surface->mins[1]);
5510 p->mins[2] = min(p->mins[2], surface->mins[2]);
5511 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5512 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5513 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5515 // merge this surface's materialflags into the waterplane
5516 p->materialflags |= t->currentmaterialflags;
5517 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5519 // merge this surface's PVS into the waterplane
5520 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5521 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5522 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5524 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5530 static void R_Water_ProcessPlanes(void)
5533 r_refdef_view_t originalview;
5534 r_refdef_view_t myview;
5536 r_waterstate_waterplane_t *p;
5539 originalview = r_refdef.view;
5541 // make sure enough textures are allocated
5542 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5544 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5546 if (!p->texture_refraction)
5547 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);
5548 if (!p->texture_refraction)
5551 else if (p->materialflags & MATERIALFLAG_CAMERA)
5553 if (!p->texture_camera)
5554 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);
5555 if (!p->texture_camera)
5559 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5561 if (!p->texture_reflection)
5562 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);
5563 if (!p->texture_reflection)
5569 r_refdef.view = originalview;
5570 r_refdef.view.showdebug = false;
5571 r_refdef.view.width = r_waterstate.waterwidth;
5572 r_refdef.view.height = r_waterstate.waterheight;
5573 r_refdef.view.useclipplane = true;
5574 myview = r_refdef.view;
5575 r_waterstate.renderingscene = true;
5576 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5578 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5580 r_refdef.view = myview;
5581 if(r_water_scissormode.integer)
5584 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5585 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5588 // render reflected scene and copy into texture
5589 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5590 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5591 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5592 r_refdef.view.clipplane = p->plane;
5594 // reverse the cullface settings for this render
5595 r_refdef.view.cullface_front = GL_FRONT;
5596 r_refdef.view.cullface_back = GL_BACK;
5597 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5599 r_refdef.view.usecustompvs = true;
5601 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5603 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5606 R_ResetViewRendering3D();
5607 R_ClearScreen(r_refdef.fogenabled);
5608 if(r_water_scissormode.integer & 2)
5609 R_View_UpdateWithScissor(myscissor);
5612 if(r_water_scissormode.integer & 1)
5613 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5616 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);
5619 // render the normal view scene and copy into texture
5620 // (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)
5621 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5623 r_refdef.view = myview;
5624 if(r_water_scissormode.integer)
5627 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5628 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5631 r_waterstate.renderingrefraction = true;
5633 r_refdef.view.clipplane = p->plane;
5634 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5635 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5637 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5639 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5640 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5641 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5642 R_RenderView_UpdateViewVectors();
5643 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5645 r_refdef.view.usecustompvs = true;
5646 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);
5650 PlaneClassify(&r_refdef.view.clipplane);
5652 R_ResetViewRendering3D();
5653 R_ClearScreen(r_refdef.fogenabled);
5654 if(r_water_scissormode.integer & 2)
5655 R_View_UpdateWithScissor(myscissor);
5658 if(r_water_scissormode.integer & 1)
5659 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5662 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);
5663 r_waterstate.renderingrefraction = false;
5665 else if (p->materialflags & MATERIALFLAG_CAMERA)
5667 r_refdef.view = myview;
5669 r_refdef.view.clipplane = p->plane;
5670 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5671 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5673 r_refdef.view.width = r_waterstate.camerawidth;
5674 r_refdef.view.height = r_waterstate.cameraheight;
5675 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5676 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5678 if(p->camera_entity)
5680 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5681 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5684 // note: all of the view is used for displaying... so
5685 // there is no use in scissoring
5687 // reverse the cullface settings for this render
5688 r_refdef.view.cullface_front = GL_FRONT;
5689 r_refdef.view.cullface_back = GL_BACK;
5690 // also reverse the view matrix
5691 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
5692 R_RenderView_UpdateViewVectors();
5693 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5695 r_refdef.view.usecustompvs = true;
5696 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);
5699 // camera needs no clipplane
5700 r_refdef.view.useclipplane = false;
5702 PlaneClassify(&r_refdef.view.clipplane);
5704 R_ResetViewRendering3D();
5705 R_ClearScreen(r_refdef.fogenabled);
5709 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);
5710 r_waterstate.renderingrefraction = false;
5714 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5715 r_waterstate.renderingscene = false;
5716 r_refdef.view = originalview;
5717 R_ResetViewRendering3D();
5718 R_ClearScreen(r_refdef.fogenabled);
5722 r_refdef.view = originalview;
5723 r_waterstate.renderingscene = false;
5724 Cvar_SetValueQuick(&r_water, 0);
5725 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5729 void R_Bloom_StartFrame(void)
5731 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5732 int viewwidth, viewheight;
5735 if (r_viewscale_fpsscaling.integer)
5737 double actualframetime;
5738 double targetframetime;
5740 actualframetime = r_refdef.lastdrawscreentime;
5741 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5742 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5743 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5744 if (r_viewscale_fpsscaling_stepsize.value > 0)
5745 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5746 viewscalefpsadjusted += adjust;
5747 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5750 viewscalefpsadjusted = 1.0f;
5752 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5754 switch(vid.renderpath)
5756 case RENDERPATH_GL20:
5757 case RENDERPATH_D3D9:
5758 case RENDERPATH_D3D10:
5759 case RENDERPATH_D3D11:
5760 case RENDERPATH_SOFT:
5761 case RENDERPATH_GLES2:
5763 case RENDERPATH_GL11:
5764 case RENDERPATH_GL13:
5765 case RENDERPATH_GLES1:
5769 // set bloomwidth and bloomheight to the bloom resolution that will be
5770 // used (often less than the screen resolution for faster rendering)
5771 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5772 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5773 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5774 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5775 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5777 // calculate desired texture sizes
5778 if (vid.support.arb_texture_non_power_of_two)
5780 screentexturewidth = vid.width;
5781 screentextureheight = vid.height;
5782 bloomtexturewidth = r_bloomstate.bloomwidth;
5783 bloomtextureheight = r_bloomstate.bloomheight;
5787 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5788 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5789 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5790 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5793 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))
5795 Cvar_SetValueQuick(&r_hdr, 0);
5796 Cvar_SetValueQuick(&r_bloom, 0);
5797 Cvar_SetValueQuick(&r_motionblur, 0);
5798 Cvar_SetValueQuick(&r_damageblur, 0);
5801 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5802 screentexturewidth = screentextureheight = 0;
5803 if (!r_hdr.integer && !r_bloom.integer)
5804 bloomtexturewidth = bloomtextureheight = 0;
5806 textype = TEXTYPE_COLORBUFFER;
5807 switch (vid.renderpath)
5809 case RENDERPATH_GL20:
5810 case RENDERPATH_GLES2:
5811 if (vid.support.ext_framebuffer_object)
5813 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5814 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5817 case RENDERPATH_GL11:
5818 case RENDERPATH_GL13:
5819 case RENDERPATH_GLES1:
5820 case RENDERPATH_D3D9:
5821 case RENDERPATH_D3D10:
5822 case RENDERPATH_D3D11:
5823 case RENDERPATH_SOFT:
5827 // allocate textures as needed
5828 if (r_bloomstate.screentexturewidth != screentexturewidth
5829 || r_bloomstate.screentextureheight != screentextureheight
5830 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5831 || r_bloomstate.bloomtextureheight != bloomtextureheight
5832 || r_bloomstate.texturetype != textype
5833 || r_bloomstate.viewfbo != r_viewfbo.integer)
5835 if (r_bloomstate.texture_bloom)
5836 R_FreeTexture(r_bloomstate.texture_bloom);
5837 r_bloomstate.texture_bloom = NULL;
5838 if (r_bloomstate.texture_screen)
5839 R_FreeTexture(r_bloomstate.texture_screen);
5840 r_bloomstate.texture_screen = NULL;
5841 if (r_bloomstate.fbo_framebuffer)
5842 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5843 r_bloomstate.fbo_framebuffer = 0;
5844 if (r_bloomstate.texture_framebuffercolor)
5845 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5846 r_bloomstate.texture_framebuffercolor = NULL;
5847 if (r_bloomstate.texture_framebufferdepth)
5848 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5849 r_bloomstate.texture_framebufferdepth = NULL;
5850 r_bloomstate.screentexturewidth = screentexturewidth;
5851 r_bloomstate.screentextureheight = screentextureheight;
5852 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5853 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5854 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5856 // FIXME: choose depth bits based on a cvar
5857 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5858 r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5859 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5860 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5861 // render depth into one texture and normalmap into the other
5865 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5866 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5867 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5868 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5869 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5872 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5873 r_bloomstate.bloomtextureheight = bloomtextureheight;
5874 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5875 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);
5876 r_bloomstate.viewfbo = r_viewfbo.integer;
5877 r_bloomstate.texturetype = textype;
5880 // when doing a reduced render (HDR) we want to use a smaller area
5881 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5882 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5883 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5884 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5885 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5887 // set up a texcoord array for the full resolution screen image
5888 // (we have to keep this around to copy back during final render)
5889 r_bloomstate.screentexcoord2f[0] = 0;
5890 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5891 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5892 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5893 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5894 r_bloomstate.screentexcoord2f[5] = 0;
5895 r_bloomstate.screentexcoord2f[6] = 0;
5896 r_bloomstate.screentexcoord2f[7] = 0;
5898 // set up a texcoord array for the reduced resolution bloom image
5899 // (which will be additive blended over the screen image)
5900 r_bloomstate.bloomtexcoord2f[0] = 0;
5901 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5902 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5903 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5904 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5905 r_bloomstate.bloomtexcoord2f[5] = 0;
5906 r_bloomstate.bloomtexcoord2f[6] = 0;
5907 r_bloomstate.bloomtexcoord2f[7] = 0;
5909 switch(vid.renderpath)
5911 case RENDERPATH_GL11:
5912 case RENDERPATH_GL13:
5913 case RENDERPATH_GL20:
5914 case RENDERPATH_SOFT:
5915 case RENDERPATH_GLES1:
5916 case RENDERPATH_GLES2:
5918 case RENDERPATH_D3D9:
5919 case RENDERPATH_D3D10:
5920 case RENDERPATH_D3D11:
5923 for (i = 0;i < 4;i++)
5925 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5926 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5927 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5928 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5934 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5936 r_bloomstate.enabled = true;
5937 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5940 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);
5942 if (r_bloomstate.fbo_framebuffer)
5943 r_refdef.view.clear = true;
5946 void R_Bloom_CopyBloomTexture(float colorscale)
5948 r_refdef.stats.bloom++;
5950 // scale down screen texture to the bloom texture size
5952 R_Mesh_SetMainRenderTargets();
5953 R_SetViewport(&r_bloomstate.viewport);
5954 GL_BlendFunc(GL_ONE, GL_ZERO);
5955 GL_Color(colorscale, colorscale, colorscale, 1);
5956 // 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...
5957 switch(vid.renderpath)
5959 case RENDERPATH_GL11:
5960 case RENDERPATH_GL13:
5961 case RENDERPATH_GL20:
5962 case RENDERPATH_GLES1:
5963 case RENDERPATH_GLES2:
5964 case RENDERPATH_SOFT:
5965 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5967 case RENDERPATH_D3D9:
5968 case RENDERPATH_D3D10:
5969 case RENDERPATH_D3D11:
5970 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5973 // TODO: do boxfilter scale-down in shader?
5974 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5975 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5976 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5978 // we now have a bloom image in the framebuffer
5979 // copy it into the bloom image texture for later processing
5980 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5981 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5984 void R_Bloom_CopyHDRTexture(void)
5986 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);
5987 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5990 void R_Bloom_MakeTexture(void)
5993 float xoffset, yoffset, r, brighten;
5995 r_refdef.stats.bloom++;
5997 R_ResetViewRendering2D();
5999 // we have a bloom image in the framebuffer
6001 R_SetViewport(&r_bloomstate.viewport);
6003 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6006 r = bound(0, r_bloom_colorexponent.value / x, 1);
6007 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6009 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6010 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6011 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6012 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6014 // copy the vertically blurred bloom view to a texture
6015 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);
6016 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6019 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6020 brighten = r_bloom_brighten.value;
6021 if (r_bloomstate.hdr)
6022 brighten *= r_hdr_range.value;
6023 brighten = sqrt(brighten);
6025 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6026 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6028 for (dir = 0;dir < 2;dir++)
6030 // blend on at multiple vertical offsets to achieve a vertical blur
6031 // TODO: do offset blends using GLSL
6032 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6033 GL_BlendFunc(GL_ONE, GL_ZERO);
6034 for (x = -range;x <= range;x++)
6036 if (!dir){xoffset = 0;yoffset = x;}
6037 else {xoffset = x;yoffset = 0;}
6038 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6039 yoffset /= (float)r_bloomstate.bloomtextureheight;
6040 // compute a texcoord array with the specified x and y offset
6041 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6042 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6043 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6044 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6045 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6046 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6047 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6048 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6049 // this r value looks like a 'dot' particle, fading sharply to
6050 // black at the edges
6051 // (probably not realistic but looks good enough)
6052 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6053 //r = brighten/(range*2+1);
6054 r = brighten / (range * 2 + 1);
6056 r *= (1 - x*x/(float)(range*range));
6057 GL_Color(r, r, r, 1);
6058 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6059 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6060 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6061 GL_BlendFunc(GL_ONE, GL_ONE);
6064 // copy the vertically blurred bloom view to a texture
6065 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);
6066 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6070 void R_HDR_RenderBloomTexture(void)
6072 int oldwidth, oldheight;
6073 float oldcolorscale;
6074 qboolean oldwaterstate;
6076 oldwaterstate = r_waterstate.enabled;
6077 oldcolorscale = r_refdef.view.colorscale;
6078 oldwidth = r_refdef.view.width;
6079 oldheight = r_refdef.view.height;
6080 r_refdef.view.width = r_bloomstate.bloomwidth;
6081 r_refdef.view.height = r_bloomstate.bloomheight;
6083 if(r_hdr.integer < 2)
6084 r_waterstate.enabled = false;
6086 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6087 // TODO: add exposure compensation features
6088 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6090 r_refdef.view.showdebug = false;
6091 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6093 R_ResetViewRendering3D();
6095 R_ClearScreen(r_refdef.fogenabled);
6096 if (r_timereport_active)
6097 R_TimeReport("HDRclear");
6100 if (r_timereport_active)
6101 R_TimeReport("visibility");
6103 // only do secondary renders with HDR if r_hdr is 2 or higher
6104 r_waterstate.numwaterplanes = 0;
6105 if (r_waterstate.enabled)
6106 R_RenderWaterPlanes();
6108 r_refdef.view.showdebug = true;
6110 r_waterstate.numwaterplanes = 0;
6112 R_ResetViewRendering2D();
6114 R_Bloom_CopyHDRTexture();
6115 R_Bloom_MakeTexture();
6117 // restore the view settings
6118 r_waterstate.enabled = oldwaterstate;
6119 r_refdef.view.width = oldwidth;
6120 r_refdef.view.height = oldheight;
6121 r_refdef.view.colorscale = oldcolorscale;
6123 R_ResetViewRendering3D();
6125 R_ClearScreen(r_refdef.fogenabled);
6126 if (r_timereport_active)
6127 R_TimeReport("viewclear");
6130 static void R_BlendView(void)
6132 unsigned int permutation;
6133 float uservecs[4][4];
6135 switch (vid.renderpath)
6137 case RENDERPATH_GL20:
6138 case RENDERPATH_D3D9:
6139 case RENDERPATH_D3D10:
6140 case RENDERPATH_D3D11:
6141 case RENDERPATH_SOFT:
6142 case RENDERPATH_GLES2:
6144 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6145 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6146 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6147 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6148 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6150 if (r_bloomstate.texture_screen)
6152 // make sure the buffer is available
6153 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6155 R_ResetViewRendering2D();
6156 R_Mesh_SetMainRenderTargets();
6158 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6160 // declare variables
6162 static float avgspeed;
6164 speed = VectorLength(cl.movement_velocity);
6166 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6167 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6169 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6170 speed = bound(0, speed, 1);
6171 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6173 // calculate values into a standard alpha
6174 cl.motionbluralpha = 1 - exp(-
6176 (r_motionblur.value * speed / 80)
6178 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6181 max(0.0001, cl.time - cl.oldtime) // fps independent
6184 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6185 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6187 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6189 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6190 GL_Color(1, 1, 1, cl.motionbluralpha);
6191 switch(vid.renderpath)
6193 case RENDERPATH_GL11:
6194 case RENDERPATH_GL13:
6195 case RENDERPATH_GL20:
6196 case RENDERPATH_GLES1:
6197 case RENDERPATH_GLES2:
6198 case RENDERPATH_SOFT:
6199 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6201 case RENDERPATH_D3D9:
6202 case RENDERPATH_D3D10:
6203 case RENDERPATH_D3D11:
6204 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6207 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6208 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6209 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6213 // copy view into the screen texture
6214 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);
6215 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6217 else if (!r_bloomstate.texture_bloom)
6219 // we may still have to do view tint...
6220 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6222 // apply a color tint to the whole view
6223 R_ResetViewRendering2D();
6224 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6225 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6226 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6227 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6228 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6230 break; // no screen processing, no bloom, skip it
6233 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6235 // render simple bloom effect
6236 // copy the screen and shrink it and darken it for the bloom process
6237 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6238 // make the bloom texture
6239 R_Bloom_MakeTexture();
6242 #if _MSC_VER >= 1400
6243 #define sscanf sscanf_s
6245 memset(uservecs, 0, sizeof(uservecs));
6246 if (r_glsl_postprocess_uservec1_enable.integer)
6247 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6248 if (r_glsl_postprocess_uservec2_enable.integer)
6249 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6250 if (r_glsl_postprocess_uservec3_enable.integer)
6251 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6252 if (r_glsl_postprocess_uservec4_enable.integer)
6253 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6255 R_ResetViewRendering2D();
6256 GL_Color(1, 1, 1, 1);
6257 GL_BlendFunc(GL_ONE, GL_ZERO);
6259 switch(vid.renderpath)
6261 case RENDERPATH_GL20:
6262 case RENDERPATH_GLES2:
6263 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6264 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6265 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6266 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6267 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6268 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]);
6269 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6270 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]);
6271 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]);
6272 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]);
6273 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]);
6274 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6275 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6276 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);
6278 case RENDERPATH_D3D9:
6280 // 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...
6281 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6282 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6283 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6284 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6285 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6286 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6287 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6288 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6289 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6290 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6291 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6292 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6293 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6294 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6297 case RENDERPATH_D3D10:
6298 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6300 case RENDERPATH_D3D11:
6301 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6303 case RENDERPATH_SOFT:
6304 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6305 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6306 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6307 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6308 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6309 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6310 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6311 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6312 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6313 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6314 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6315 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6316 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6317 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6322 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6323 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6325 case RENDERPATH_GL11:
6326 case RENDERPATH_GL13:
6327 case RENDERPATH_GLES1:
6328 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6330 // apply a color tint to the whole view
6331 R_ResetViewRendering2D();
6332 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6333 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6334 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6335 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6336 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6342 matrix4x4_t r_waterscrollmatrix;
6344 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6346 if (r_refdef.fog_density)
6348 r_refdef.fogcolor[0] = r_refdef.fog_red;
6349 r_refdef.fogcolor[1] = r_refdef.fog_green;
6350 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6352 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6353 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6354 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6355 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6359 VectorCopy(r_refdef.fogcolor, fogvec);
6360 // color.rgb *= ContrastBoost * SceneBrightness;
6361 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6362 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6363 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6364 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6369 void R_UpdateVariables(void)
6373 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6375 r_refdef.farclip = r_farclip_base.value;
6376 if (r_refdef.scene.worldmodel)
6377 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6378 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6380 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6381 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6382 r_refdef.polygonfactor = 0;
6383 r_refdef.polygonoffset = 0;
6384 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6385 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6387 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6388 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6389 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6390 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6391 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6392 if (FAKELIGHT_ENABLED)
6394 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6396 if (r_showsurfaces.integer)
6398 r_refdef.scene.rtworld = false;
6399 r_refdef.scene.rtworldshadows = false;
6400 r_refdef.scene.rtdlight = false;
6401 r_refdef.scene.rtdlightshadows = false;
6402 r_refdef.lightmapintensity = 0;
6405 if (gamemode == GAME_NEHAHRA)
6407 if (gl_fogenable.integer)
6409 r_refdef.oldgl_fogenable = true;
6410 r_refdef.fog_density = gl_fogdensity.value;
6411 r_refdef.fog_red = gl_fogred.value;
6412 r_refdef.fog_green = gl_foggreen.value;
6413 r_refdef.fog_blue = gl_fogblue.value;
6414 r_refdef.fog_alpha = 1;
6415 r_refdef.fog_start = 0;
6416 r_refdef.fog_end = gl_skyclip.value;
6417 r_refdef.fog_height = 1<<30;
6418 r_refdef.fog_fadedepth = 128;
6420 else if (r_refdef.oldgl_fogenable)
6422 r_refdef.oldgl_fogenable = false;
6423 r_refdef.fog_density = 0;
6424 r_refdef.fog_red = 0;
6425 r_refdef.fog_green = 0;
6426 r_refdef.fog_blue = 0;
6427 r_refdef.fog_alpha = 0;
6428 r_refdef.fog_start = 0;
6429 r_refdef.fog_end = 0;
6430 r_refdef.fog_height = 1<<30;
6431 r_refdef.fog_fadedepth = 128;
6435 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6436 r_refdef.fog_start = max(0, r_refdef.fog_start);
6437 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6439 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6441 if (r_refdef.fog_density && r_drawfog.integer)
6443 r_refdef.fogenabled = true;
6444 // this is the point where the fog reaches 0.9986 alpha, which we
6445 // consider a good enough cutoff point for the texture
6446 // (0.9986 * 256 == 255.6)
6447 if (r_fog_exp2.integer)
6448 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6450 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6451 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6452 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6453 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6454 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6455 R_BuildFogHeightTexture();
6456 // fog color was already set
6457 // update the fog texture
6458 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)
6459 R_BuildFogTexture();
6460 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6461 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6464 r_refdef.fogenabled = false;
6466 switch(vid.renderpath)
6468 case RENDERPATH_GL20:
6469 case RENDERPATH_D3D9:
6470 case RENDERPATH_D3D10:
6471 case RENDERPATH_D3D11:
6472 case RENDERPATH_SOFT:
6473 case RENDERPATH_GLES2:
6474 if(v_glslgamma.integer && !vid_gammatables_trivial)
6476 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6478 // build GLSL gamma texture
6479 #define RAMPWIDTH 256
6480 unsigned short ramp[RAMPWIDTH * 3];
6481 unsigned char rampbgr[RAMPWIDTH][4];
6484 r_texture_gammaramps_serial = vid_gammatables_serial;
6486 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6487 for(i = 0; i < RAMPWIDTH; ++i)
6489 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6490 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6491 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6494 if (r_texture_gammaramps)
6496 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6500 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6506 // remove GLSL gamma texture
6509 case RENDERPATH_GL11:
6510 case RENDERPATH_GL13:
6511 case RENDERPATH_GLES1:
6516 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6517 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6523 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6524 if( scenetype != r_currentscenetype ) {
6525 // store the old scenetype
6526 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6527 r_currentscenetype = scenetype;
6528 // move in the new scene
6529 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6538 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6540 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6541 if( scenetype == r_currentscenetype ) {
6542 return &r_refdef.scene;
6544 return &r_scenes_store[ scenetype ];
6553 int dpsoftrast_test;
6554 void R_RenderView(void)
6556 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6558 dpsoftrast_test = r_test.integer;
6560 if (r_timereport_active)
6561 R_TimeReport("start");
6562 r_textureframe++; // used only by R_GetCurrentTexture
6563 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6565 if(R_CompileShader_CheckStaticParms())
6568 if (!r_drawentities.integer)
6569 r_refdef.scene.numentities = 0;
6571 R_AnimCache_ClearCache();
6572 R_FrameData_NewFrame();
6574 /* adjust for stereo display */
6575 if(R_Stereo_Active())
6577 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);
6578 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6581 if (r_refdef.view.isoverlay)
6583 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6584 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6585 R_TimeReport("depthclear");
6587 r_refdef.view.showdebug = false;
6589 r_waterstate.enabled = false;
6590 r_waterstate.numwaterplanes = 0;
6594 r_refdef.view.matrix = originalmatrix;
6600 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6602 r_refdef.view.matrix = originalmatrix;
6603 return; //Host_Error ("R_RenderView: NULL worldmodel");
6606 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6608 R_RenderView_UpdateViewVectors();
6610 R_Shadow_UpdateWorldLightSelection();
6612 R_Bloom_StartFrame();
6613 R_Water_StartFrame();
6616 if (r_timereport_active)
6617 R_TimeReport("viewsetup");
6619 R_ResetViewRendering3D();
6621 if (r_refdef.view.clear || r_refdef.fogenabled)
6623 R_ClearScreen(r_refdef.fogenabled);
6624 if (r_timereport_active)
6625 R_TimeReport("viewclear");
6627 r_refdef.view.clear = true;
6629 // this produces a bloom texture to be used in R_BlendView() later
6630 if (r_bloomstate.hdr)
6632 R_HDR_RenderBloomTexture();
6633 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6634 r_textureframe++; // used only by R_GetCurrentTexture
6637 r_refdef.view.showdebug = true;
6640 if (r_timereport_active)
6641 R_TimeReport("visibility");
6643 r_waterstate.numwaterplanes = 0;
6644 if (r_waterstate.enabled)
6645 R_RenderWaterPlanes();
6648 r_waterstate.numwaterplanes = 0;
6651 if (r_timereport_active)
6652 R_TimeReport("blendview");
6654 GL_Scissor(0, 0, vid.width, vid.height);
6655 GL_ScissorTest(false);
6657 r_refdef.view.matrix = originalmatrix;
6662 void R_RenderWaterPlanes(void)
6664 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6666 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6667 if (r_timereport_active)
6668 R_TimeReport("waterworld");
6671 // don't let sound skip if going slow
6672 if (r_refdef.scene.extraupdate)
6675 R_DrawModelsAddWaterPlanes();
6676 if (r_timereport_active)
6677 R_TimeReport("watermodels");
6679 if (r_waterstate.numwaterplanes)
6681 R_Water_ProcessPlanes();
6682 if (r_timereport_active)
6683 R_TimeReport("waterscenes");
6687 extern void R_DrawLightningBeams (void);
6688 extern void VM_CL_AddPolygonsToMeshQueue (void);
6689 extern void R_DrawPortals (void);
6690 extern cvar_t cl_locs_show;
6691 static void R_DrawLocs(void);
6692 static void R_DrawEntityBBoxes(void);
6693 static void R_DrawModelDecals(void);
6694 extern void R_DrawModelShadows(void);
6695 extern void R_DrawModelShadowMaps(void);
6696 extern cvar_t cl_decals_newsystem;
6697 extern qboolean r_shadow_usingdeferredprepass;
6698 void R_RenderScene(void)
6700 qboolean shadowmapping = false;
6702 if (r_timereport_active)
6703 R_TimeReport("beginscene");
6705 r_refdef.stats.renders++;
6709 // don't let sound skip if going slow
6710 if (r_refdef.scene.extraupdate)
6713 R_MeshQueue_BeginScene();
6717 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);
6719 if (r_timereport_active)
6720 R_TimeReport("skystartframe");
6722 if (cl.csqc_vidvars.drawworld)
6724 // don't let sound skip if going slow
6725 if (r_refdef.scene.extraupdate)
6728 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6730 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6731 if (r_timereport_active)
6732 R_TimeReport("worldsky");
6735 if (R_DrawBrushModelsSky() && r_timereport_active)
6736 R_TimeReport("bmodelsky");
6738 if (skyrendermasked && skyrenderlater)
6740 // we have to force off the water clipping plane while rendering sky
6744 if (r_timereport_active)
6745 R_TimeReport("sky");
6749 R_AnimCache_CacheVisibleEntities();
6750 if (r_timereport_active)
6751 R_TimeReport("animation");
6753 R_Shadow_PrepareLights();
6754 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6755 R_Shadow_PrepareModelShadows();
6756 if (r_timereport_active)
6757 R_TimeReport("preparelights");
6759 if (R_Shadow_ShadowMappingEnabled())
6760 shadowmapping = true;
6762 if (r_shadow_usingdeferredprepass)
6763 R_Shadow_DrawPrepass();
6765 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6767 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6768 if (r_timereport_active)
6769 R_TimeReport("worlddepth");
6771 if (r_depthfirst.integer >= 2)
6773 R_DrawModelsDepth();
6774 if (r_timereport_active)
6775 R_TimeReport("modeldepth");
6778 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6780 R_DrawModelShadowMaps();
6781 R_ResetViewRendering3D();
6782 // don't let sound skip if going slow
6783 if (r_refdef.scene.extraupdate)
6787 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6789 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6790 if (r_timereport_active)
6791 R_TimeReport("world");
6794 // don't let sound skip if going slow
6795 if (r_refdef.scene.extraupdate)
6799 if (r_timereport_active)
6800 R_TimeReport("models");
6802 // don't let sound skip if going slow
6803 if (r_refdef.scene.extraupdate)
6806 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6808 R_DrawModelShadows();
6809 R_ResetViewRendering3D();
6810 // don't let sound skip if going slow
6811 if (r_refdef.scene.extraupdate)
6815 if (!r_shadow_usingdeferredprepass)
6817 R_Shadow_DrawLights();
6818 if (r_timereport_active)
6819 R_TimeReport("rtlights");
6822 // don't let sound skip if going slow
6823 if (r_refdef.scene.extraupdate)
6826 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6828 R_DrawModelShadows();
6829 R_ResetViewRendering3D();
6830 // don't let sound skip if going slow
6831 if (r_refdef.scene.extraupdate)
6835 if (cl.csqc_vidvars.drawworld)
6837 if (cl_decals_newsystem.integer)
6839 R_DrawModelDecals();
6840 if (r_timereport_active)
6841 R_TimeReport("modeldecals");
6846 if (r_timereport_active)
6847 R_TimeReport("decals");
6851 if (r_timereport_active)
6852 R_TimeReport("particles");
6855 if (r_timereport_active)
6856 R_TimeReport("explosions");
6858 R_DrawLightningBeams();
6859 if (r_timereport_active)
6860 R_TimeReport("lightning");
6863 VM_CL_AddPolygonsToMeshQueue();
6865 if (r_refdef.view.showdebug)
6867 if (cl_locs_show.integer)
6870 if (r_timereport_active)
6871 R_TimeReport("showlocs");
6874 if (r_drawportals.integer)
6877 if (r_timereport_active)
6878 R_TimeReport("portals");
6881 if (r_showbboxes.value > 0)
6883 R_DrawEntityBBoxes();
6884 if (r_timereport_active)
6885 R_TimeReport("bboxes");
6889 if (r_transparent.integer)
6891 R_MeshQueue_RenderTransparent();
6892 if (r_timereport_active)
6893 R_TimeReport("drawtrans");
6896 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 || r_showoverdraw.value > 0))
6898 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6899 if (r_timereport_active)
6900 R_TimeReport("worlddebug");
6901 R_DrawModelsDebug();
6902 if (r_timereport_active)
6903 R_TimeReport("modeldebug");
6906 if (cl.csqc_vidvars.drawworld)
6908 R_Shadow_DrawCoronas();
6909 if (r_timereport_active)
6910 R_TimeReport("coronas");
6915 GL_DepthTest(false);
6916 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6917 GL_Color(1, 1, 1, 1);
6918 qglBegin(GL_POLYGON);
6919 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6920 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6921 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6922 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6924 qglBegin(GL_POLYGON);
6925 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]);
6926 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]);
6927 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]);
6928 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]);
6930 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6934 // don't let sound skip if going slow
6935 if (r_refdef.scene.extraupdate)
6938 R_ResetViewRendering2D();
6941 static const unsigned short bboxelements[36] =
6951 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6954 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6956 RSurf_ActiveWorldEntity();
6958 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6959 GL_DepthMask(false);
6960 GL_DepthRange(0, 1);
6961 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6962 // R_Mesh_ResetTextureState();
6964 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6965 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6966 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6967 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6968 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6969 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6970 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6971 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6972 R_FillColors(color4f, 8, cr, cg, cb, ca);
6973 if (r_refdef.fogenabled)
6975 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6977 f1 = RSurf_FogVertex(v);
6979 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6980 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6981 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6984 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6985 R_Mesh_ResetTextureState();
6986 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6987 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6990 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6994 prvm_edict_t *edict;
6995 prvm_prog_t *prog_save = prog;
6997 // this function draws bounding boxes of server entities
7001 GL_CullFace(GL_NONE);
7002 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7006 for (i = 0;i < numsurfaces;i++)
7008 edict = PRVM_EDICT_NUM(surfacelist[i]);
7009 switch ((int)edict->fields.server->solid)
7011 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7012 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7013 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7014 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7015 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7016 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7018 color[3] *= r_showbboxes.value;
7019 color[3] = bound(0, color[3], 1);
7020 GL_DepthTest(!r_showdisabledepthtest.integer);
7021 GL_CullFace(r_refdef.view.cullface_front);
7022 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7028 static void R_DrawEntityBBoxes(void)
7031 prvm_edict_t *edict;
7033 prvm_prog_t *prog_save = prog;
7035 // this function draws bounding boxes of server entities
7041 for (i = 0;i < prog->num_edicts;i++)
7043 edict = PRVM_EDICT_NUM(i);
7044 if (edict->priv.server->free)
7046 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7047 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7049 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7051 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7052 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7058 static const int nomodelelement3i[24] =
7070 static const unsigned short nomodelelement3s[24] =
7082 static const float nomodelvertex3f[6*3] =
7092 static const float nomodelcolor4f[6*4] =
7094 0.0f, 0.0f, 0.5f, 1.0f,
7095 0.0f, 0.0f, 0.5f, 1.0f,
7096 0.0f, 0.5f, 0.0f, 1.0f,
7097 0.0f, 0.5f, 0.0f, 1.0f,
7098 0.5f, 0.0f, 0.0f, 1.0f,
7099 0.5f, 0.0f, 0.0f, 1.0f
7102 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7108 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);
7110 // this is only called once per entity so numsurfaces is always 1, and
7111 // surfacelist is always {0}, so this code does not handle batches
7113 if (rsurface.ent_flags & RENDER_ADDITIVE)
7115 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7116 GL_DepthMask(false);
7118 else if (rsurface.colormod[3] < 1)
7120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7121 GL_DepthMask(false);
7125 GL_BlendFunc(GL_ONE, GL_ZERO);
7128 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7129 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7130 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7131 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7132 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7133 for (i = 0, c = color4f;i < 6;i++, c += 4)
7135 c[0] *= rsurface.colormod[0];
7136 c[1] *= rsurface.colormod[1];
7137 c[2] *= rsurface.colormod[2];
7138 c[3] *= rsurface.colormod[3];
7140 if (r_refdef.fogenabled)
7142 for (i = 0, c = color4f;i < 6;i++, c += 4)
7144 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7146 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7147 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7148 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7151 // R_Mesh_ResetTextureState();
7152 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7153 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7154 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7157 void R_DrawNoModel(entity_render_t *ent)
7160 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7161 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7162 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7164 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7167 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7169 vec3_t right1, right2, diff, normal;
7171 VectorSubtract (org2, org1, normal);
7173 // calculate 'right' vector for start
7174 VectorSubtract (r_refdef.view.origin, org1, diff);
7175 CrossProduct (normal, diff, right1);
7176 VectorNormalize (right1);
7178 // calculate 'right' vector for end
7179 VectorSubtract (r_refdef.view.origin, org2, diff);
7180 CrossProduct (normal, diff, right2);
7181 VectorNormalize (right2);
7183 vert[ 0] = org1[0] + width * right1[0];
7184 vert[ 1] = org1[1] + width * right1[1];
7185 vert[ 2] = org1[2] + width * right1[2];
7186 vert[ 3] = org1[0] - width * right1[0];
7187 vert[ 4] = org1[1] - width * right1[1];
7188 vert[ 5] = org1[2] - width * right1[2];
7189 vert[ 6] = org2[0] - width * right2[0];
7190 vert[ 7] = org2[1] - width * right2[1];
7191 vert[ 8] = org2[2] - width * right2[2];
7192 vert[ 9] = org2[0] + width * right2[0];
7193 vert[10] = org2[1] + width * right2[1];
7194 vert[11] = org2[2] + width * right2[2];
7197 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)
7199 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7200 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7201 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7202 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7203 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7204 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7205 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7206 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7207 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7208 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7209 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7210 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7213 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7218 VectorSet(v, x, y, z);
7219 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7220 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7222 if (i == mesh->numvertices)
7224 if (mesh->numvertices < mesh->maxvertices)
7226 VectorCopy(v, vertex3f);
7227 mesh->numvertices++;
7229 return mesh->numvertices;
7235 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7239 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7240 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7241 e = mesh->element3i + mesh->numtriangles * 3;
7242 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7244 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7245 if (mesh->numtriangles < mesh->maxtriangles)
7250 mesh->numtriangles++;
7252 element[1] = element[2];
7256 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7260 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7261 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7262 e = mesh->element3i + mesh->numtriangles * 3;
7263 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7265 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7266 if (mesh->numtriangles < mesh->maxtriangles)
7271 mesh->numtriangles++;
7273 element[1] = element[2];
7277 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7278 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7280 int planenum, planenum2;
7283 mplane_t *plane, *plane2;
7285 double temppoints[2][256*3];
7286 // figure out how large a bounding box we need to properly compute this brush
7288 for (w = 0;w < numplanes;w++)
7289 maxdist = max(maxdist, fabs(planes[w].dist));
7290 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7291 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7292 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7296 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7297 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7299 if (planenum2 == planenum)
7301 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);
7304 if (tempnumpoints < 3)
7306 // generate elements forming a triangle fan for this polygon
7307 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7311 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)
7313 texturelayer_t *layer;
7314 layer = t->currentlayers + t->currentnumlayers++;
7316 layer->depthmask = depthmask;
7317 layer->blendfunc1 = blendfunc1;
7318 layer->blendfunc2 = blendfunc2;
7319 layer->texture = texture;
7320 layer->texmatrix = *matrix;
7321 layer->color[0] = r;
7322 layer->color[1] = g;
7323 layer->color[2] = b;
7324 layer->color[3] = a;
7327 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7329 if(parms[0] == 0 && parms[1] == 0)
7331 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7332 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7337 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7340 index = parms[2] + r_refdef.scene.time * parms[3];
7341 index -= floor(index);
7342 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7345 case Q3WAVEFUNC_NONE:
7346 case Q3WAVEFUNC_NOISE:
7347 case Q3WAVEFUNC_COUNT:
7350 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7351 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7352 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7353 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7354 case Q3WAVEFUNC_TRIANGLE:
7356 f = index - floor(index);
7367 f = parms[0] + parms[1] * f;
7368 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7369 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7373 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7378 matrix4x4_t matrix, temp;
7379 switch(tcmod->tcmod)
7383 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7384 matrix = r_waterscrollmatrix;
7386 matrix = identitymatrix;
7388 case Q3TCMOD_ENTITYTRANSLATE:
7389 // this is used in Q3 to allow the gamecode to control texcoord
7390 // scrolling on the entity, which is not supported in darkplaces yet.
7391 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7393 case Q3TCMOD_ROTATE:
7394 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7395 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7396 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7399 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7401 case Q3TCMOD_SCROLL:
7402 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7404 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7405 w = (int) tcmod->parms[0];
7406 h = (int) tcmod->parms[1];
7407 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7409 idx = (int) floor(f * w * h);
7410 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7412 case Q3TCMOD_STRETCH:
7413 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7414 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7416 case Q3TCMOD_TRANSFORM:
7417 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7418 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7419 VectorSet(tcmat + 6, 0 , 0 , 1);
7420 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7421 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7423 case Q3TCMOD_TURBULENT:
7424 // this is handled in the RSurf_PrepareVertices function
7425 matrix = identitymatrix;
7429 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7432 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7434 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7435 char name[MAX_QPATH];
7436 skinframe_t *skinframe;
7437 unsigned char pixels[296*194];
7438 strlcpy(cache->name, skinname, sizeof(cache->name));
7439 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7440 if (developer_loading.integer)
7441 Con_Printf("loading %s\n", name);
7442 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7443 if (!skinframe || !skinframe->base)
7446 fs_offset_t filesize;
7448 f = FS_LoadFile(name, tempmempool, true, &filesize);
7451 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7452 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7456 cache->skinframe = skinframe;
7459 texture_t *R_GetCurrentTexture(texture_t *t)
7462 const entity_render_t *ent = rsurface.entity;
7463 dp_model_t *model = ent->model;
7464 q3shaderinfo_layer_tcmod_t *tcmod;
7466 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7467 return t->currentframe;
7468 t->update_lastrenderframe = r_textureframe;
7469 t->update_lastrenderentity = (void *)ent;
7471 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7472 t->camera_entity = ent->entitynumber;
7474 t->camera_entity = 0;
7476 // switch to an alternate material if this is a q1bsp animated material
7478 texture_t *texture = t;
7479 int s = rsurface.ent_skinnum;
7480 if ((unsigned int)s >= (unsigned int)model->numskins)
7482 if (model->skinscenes)
7484 if (model->skinscenes[s].framecount > 1)
7485 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7487 s = model->skinscenes[s].firstframe;
7490 t = t + s * model->num_surfaces;
7493 // use an alternate animation if the entity's frame is not 0,
7494 // and only if the texture has an alternate animation
7495 if (rsurface.ent_alttextures && t->anim_total[1])
7496 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7498 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7500 texture->currentframe = t;
7503 // update currentskinframe to be a qw skin or animation frame
7504 if (rsurface.ent_qwskin >= 0)
7506 i = rsurface.ent_qwskin;
7507 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7509 r_qwskincache_size = cl.maxclients;
7511 Mem_Free(r_qwskincache);
7512 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7514 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7515 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7516 t->currentskinframe = r_qwskincache[i].skinframe;
7517 if (t->currentskinframe == NULL)
7518 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7520 else if (t->numskinframes >= 2)
7521 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7522 if (t->backgroundnumskinframes >= 2)
7523 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7525 t->currentmaterialflags = t->basematerialflags;
7526 t->currentalpha = rsurface.colormod[3];
7527 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7528 t->currentalpha *= r_wateralpha.value;
7529 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7530 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7531 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7532 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7533 if (!(rsurface.ent_flags & RENDER_LIGHT))
7534 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7535 else if (FAKELIGHT_ENABLED)
7537 // no modellight if using fakelight for the map
7539 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7541 // pick a model lighting mode
7542 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7543 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7545 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7547 if (rsurface.ent_flags & RENDER_ADDITIVE)
7548 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7549 else if (t->currentalpha < 1)
7550 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7551 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7552 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7553 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7554 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7555 if (t->backgroundnumskinframes)
7556 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7557 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7559 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7560 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7563 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7564 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7565 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7567 // there is no tcmod
7568 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7570 t->currenttexmatrix = r_waterscrollmatrix;
7571 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7573 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7575 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7576 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7579 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7580 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7581 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7582 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7584 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7585 if (t->currentskinframe->qpixels)
7586 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7587 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7588 if (!t->basetexture)
7589 t->basetexture = r_texture_notexture;
7590 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7591 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7592 t->nmaptexture = t->currentskinframe->nmap;
7593 if (!t->nmaptexture)
7594 t->nmaptexture = r_texture_blanknormalmap;
7595 t->glosstexture = r_texture_black;
7596 t->glowtexture = t->currentskinframe->glow;
7597 t->fogtexture = t->currentskinframe->fog;
7598 t->reflectmasktexture = t->currentskinframe->reflect;
7599 if (t->backgroundnumskinframes)
7601 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7602 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7603 t->backgroundglosstexture = r_texture_black;
7604 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7605 if (!t->backgroundnmaptexture)
7606 t->backgroundnmaptexture = r_texture_blanknormalmap;
7610 t->backgroundbasetexture = r_texture_white;
7611 t->backgroundnmaptexture = r_texture_blanknormalmap;
7612 t->backgroundglosstexture = r_texture_black;
7613 t->backgroundglowtexture = NULL;
7615 t->specularpower = r_shadow_glossexponent.value;
7616 // TODO: store reference values for these in the texture?
7617 t->specularscale = 0;
7618 if (r_shadow_gloss.integer > 0)
7620 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7622 if (r_shadow_glossintensity.value > 0)
7624 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7625 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7626 t->specularscale = r_shadow_glossintensity.value;
7629 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7631 t->glosstexture = r_texture_white;
7632 t->backgroundglosstexture = r_texture_white;
7633 t->specularscale = r_shadow_gloss2intensity.value;
7634 t->specularpower = r_shadow_gloss2exponent.value;
7637 t->specularscale *= t->specularscalemod;
7638 t->specularpower *= t->specularpowermod;
7640 // lightmaps mode looks bad with dlights using actual texturing, so turn
7641 // off the colormap and glossmap, but leave the normalmap on as it still
7642 // accurately represents the shading involved
7643 if (gl_lightmaps.integer)
7645 t->basetexture = r_texture_grey128;
7646 t->pantstexture = r_texture_black;
7647 t->shirttexture = r_texture_black;
7648 t->nmaptexture = r_texture_blanknormalmap;
7649 t->glosstexture = r_texture_black;
7650 t->glowtexture = NULL;
7651 t->fogtexture = NULL;
7652 t->reflectmasktexture = NULL;
7653 t->backgroundbasetexture = NULL;
7654 t->backgroundnmaptexture = r_texture_blanknormalmap;
7655 t->backgroundglosstexture = r_texture_black;
7656 t->backgroundglowtexture = NULL;
7657 t->specularscale = 0;
7658 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7661 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7662 VectorClear(t->dlightcolor);
7663 t->currentnumlayers = 0;
7664 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7666 int blendfunc1, blendfunc2;
7668 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7670 blendfunc1 = GL_SRC_ALPHA;
7671 blendfunc2 = GL_ONE;
7673 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7675 blendfunc1 = GL_SRC_ALPHA;
7676 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7678 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7680 blendfunc1 = t->customblendfunc[0];
7681 blendfunc2 = t->customblendfunc[1];
7685 blendfunc1 = GL_ONE;
7686 blendfunc2 = GL_ZERO;
7688 // don't colormod evilblend textures
7689 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7690 VectorSet(t->lightmapcolor, 1, 1, 1);
7691 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7692 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7694 // fullbright is not affected by r_refdef.lightmapintensity
7695 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]);
7696 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7697 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]);
7698 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7699 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]);
7703 vec3_t ambientcolor;
7705 // set the color tint used for lights affecting this surface
7706 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7708 // q3bsp has no lightmap updates, so the lightstylevalue that
7709 // would normally be baked into the lightmap must be
7710 // applied to the color
7711 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7712 if (model->type == mod_brushq3)
7713 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7714 colorscale *= r_refdef.lightmapintensity;
7715 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7716 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7717 // basic lit geometry
7718 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]);
7719 // add pants/shirt if needed
7720 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7721 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]);
7722 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7723 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]);
7724 // now add ambient passes if needed
7725 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7727 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]);
7728 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7729 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]);
7730 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7731 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]);
7734 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7735 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]);
7736 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7738 // if this is opaque use alpha blend which will darken the earlier
7741 // if this is an alpha blended material, all the earlier passes
7742 // were darkened by fog already, so we only need to add the fog
7743 // color ontop through the fog mask texture
7745 // if this is an additive blended material, all the earlier passes
7746 // were darkened by fog already, and we should not add fog color
7747 // (because the background was not darkened, there is no fog color
7748 // that was lost behind it).
7749 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]);
7753 return t->currentframe;
7756 rsurfacestate_t rsurface;
7758 void RSurf_ActiveWorldEntity(void)
7760 dp_model_t *model = r_refdef.scene.worldmodel;
7761 //if (rsurface.entity == r_refdef.scene.worldentity)
7763 rsurface.entity = r_refdef.scene.worldentity;
7764 rsurface.skeleton = NULL;
7765 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7766 rsurface.ent_skinnum = 0;
7767 rsurface.ent_qwskin = -1;
7768 rsurface.ent_shadertime = 0;
7769 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7770 rsurface.matrix = identitymatrix;
7771 rsurface.inversematrix = identitymatrix;
7772 rsurface.matrixscale = 1;
7773 rsurface.inversematrixscale = 1;
7774 R_EntityMatrix(&identitymatrix);
7775 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7776 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7777 rsurface.fograngerecip = r_refdef.fograngerecip;
7778 rsurface.fogheightfade = r_refdef.fogheightfade;
7779 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7780 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7781 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7782 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7783 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7784 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7785 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7786 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7787 rsurface.colormod[3] = 1;
7788 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);
7789 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7790 rsurface.frameblend[0].lerp = 1;
7791 rsurface.ent_alttextures = false;
7792 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7793 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7794 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7795 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7797 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7798 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7800 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7801 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7802 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7803 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7804 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7805 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7806 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7807 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7808 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7809 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7810 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7811 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7812 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7813 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7814 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7815 rsurface.modelelement3i = model->surfmesh.data_element3i;
7816 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7817 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7818 rsurface.modelelement3s = model->surfmesh.data_element3s;
7819 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7820 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7821 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7822 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7823 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7824 rsurface.modelsurfaces = model->data_surfaces;
7825 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7826 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7827 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7828 rsurface.modelgeneratedvertex = false;
7829 rsurface.batchgeneratedvertex = false;
7830 rsurface.batchfirstvertex = 0;
7831 rsurface.batchnumvertices = 0;
7832 rsurface.batchfirsttriangle = 0;
7833 rsurface.batchnumtriangles = 0;
7834 rsurface.batchvertex3f = NULL;
7835 rsurface.batchvertex3f_vertexbuffer = NULL;
7836 rsurface.batchvertex3f_bufferoffset = 0;
7837 rsurface.batchsvector3f = NULL;
7838 rsurface.batchsvector3f_vertexbuffer = NULL;
7839 rsurface.batchsvector3f_bufferoffset = 0;
7840 rsurface.batchtvector3f = NULL;
7841 rsurface.batchtvector3f_vertexbuffer = NULL;
7842 rsurface.batchtvector3f_bufferoffset = 0;
7843 rsurface.batchnormal3f = NULL;
7844 rsurface.batchnormal3f_vertexbuffer = NULL;
7845 rsurface.batchnormal3f_bufferoffset = 0;
7846 rsurface.batchlightmapcolor4f = NULL;
7847 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7848 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7849 rsurface.batchtexcoordtexture2f = NULL;
7850 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7851 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7852 rsurface.batchtexcoordlightmap2f = NULL;
7853 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7854 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7855 rsurface.batchvertexmesh = NULL;
7856 rsurface.batchvertexmeshbuffer = NULL;
7857 rsurface.batchvertex3fbuffer = NULL;
7858 rsurface.batchelement3i = NULL;
7859 rsurface.batchelement3i_indexbuffer = NULL;
7860 rsurface.batchelement3i_bufferoffset = 0;
7861 rsurface.batchelement3s = NULL;
7862 rsurface.batchelement3s_indexbuffer = NULL;
7863 rsurface.batchelement3s_bufferoffset = 0;
7864 rsurface.passcolor4f = NULL;
7865 rsurface.passcolor4f_vertexbuffer = NULL;
7866 rsurface.passcolor4f_bufferoffset = 0;
7869 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7871 dp_model_t *model = ent->model;
7872 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7874 rsurface.entity = (entity_render_t *)ent;
7875 rsurface.skeleton = ent->skeleton;
7876 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7877 rsurface.ent_skinnum = ent->skinnum;
7878 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;
7879 rsurface.ent_shadertime = ent->shadertime;
7880 rsurface.ent_flags = ent->flags;
7881 rsurface.matrix = ent->matrix;
7882 rsurface.inversematrix = ent->inversematrix;
7883 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7884 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7885 R_EntityMatrix(&rsurface.matrix);
7886 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7887 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7888 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7889 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7890 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7891 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7892 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7893 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7894 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7895 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7896 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7897 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7898 rsurface.colormod[3] = ent->alpha;
7899 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7900 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7901 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7902 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7903 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7904 if (ent->model->brush.submodel && !prepass)
7906 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7907 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7909 if (model->surfmesh.isanimated && model->AnimateVertices)
7911 if (ent->animcache_vertex3f)
7913 rsurface.modelvertex3f = ent->animcache_vertex3f;
7914 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7915 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7916 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7917 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7918 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7919 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7921 else if (wanttangents)
7923 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7924 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7925 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7926 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7927 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7928 rsurface.modelvertexmesh = NULL;
7929 rsurface.modelvertexmeshbuffer = NULL;
7930 rsurface.modelvertex3fbuffer = NULL;
7932 else if (wantnormals)
7934 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7935 rsurface.modelsvector3f = NULL;
7936 rsurface.modeltvector3f = NULL;
7937 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7938 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7939 rsurface.modelvertexmesh = NULL;
7940 rsurface.modelvertexmeshbuffer = NULL;
7941 rsurface.modelvertex3fbuffer = NULL;
7945 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7946 rsurface.modelsvector3f = NULL;
7947 rsurface.modeltvector3f = NULL;
7948 rsurface.modelnormal3f = NULL;
7949 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7950 rsurface.modelvertexmesh = NULL;
7951 rsurface.modelvertexmeshbuffer = NULL;
7952 rsurface.modelvertex3fbuffer = NULL;
7954 rsurface.modelvertex3f_vertexbuffer = 0;
7955 rsurface.modelvertex3f_bufferoffset = 0;
7956 rsurface.modelsvector3f_vertexbuffer = 0;
7957 rsurface.modelsvector3f_bufferoffset = 0;
7958 rsurface.modeltvector3f_vertexbuffer = 0;
7959 rsurface.modeltvector3f_bufferoffset = 0;
7960 rsurface.modelnormal3f_vertexbuffer = 0;
7961 rsurface.modelnormal3f_bufferoffset = 0;
7962 rsurface.modelgeneratedvertex = true;
7966 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7967 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7968 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7969 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7970 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7971 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7972 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7973 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7975 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7976 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7978 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7979 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7980 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7981 rsurface.modelgeneratedvertex = false;
7983 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7984 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7985 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7986 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7987 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7988 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7989 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7990 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7991 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7992 rsurface.modelelement3i = model->surfmesh.data_element3i;
7993 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7994 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7995 rsurface.modelelement3s = model->surfmesh.data_element3s;
7996 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7997 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7998 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7999 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8000 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8001 rsurface.modelsurfaces = model->data_surfaces;
8002 rsurface.batchgeneratedvertex = false;
8003 rsurface.batchfirstvertex = 0;
8004 rsurface.batchnumvertices = 0;
8005 rsurface.batchfirsttriangle = 0;
8006 rsurface.batchnumtriangles = 0;
8007 rsurface.batchvertex3f = NULL;
8008 rsurface.batchvertex3f_vertexbuffer = NULL;
8009 rsurface.batchvertex3f_bufferoffset = 0;
8010 rsurface.batchsvector3f = NULL;
8011 rsurface.batchsvector3f_vertexbuffer = NULL;
8012 rsurface.batchsvector3f_bufferoffset = 0;
8013 rsurface.batchtvector3f = NULL;
8014 rsurface.batchtvector3f_vertexbuffer = NULL;
8015 rsurface.batchtvector3f_bufferoffset = 0;
8016 rsurface.batchnormal3f = NULL;
8017 rsurface.batchnormal3f_vertexbuffer = NULL;
8018 rsurface.batchnormal3f_bufferoffset = 0;
8019 rsurface.batchlightmapcolor4f = NULL;
8020 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8021 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8022 rsurface.batchtexcoordtexture2f = NULL;
8023 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8024 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8025 rsurface.batchtexcoordlightmap2f = NULL;
8026 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8027 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8028 rsurface.batchvertexmesh = NULL;
8029 rsurface.batchvertexmeshbuffer = NULL;
8030 rsurface.batchvertex3fbuffer = NULL;
8031 rsurface.batchelement3i = NULL;
8032 rsurface.batchelement3i_indexbuffer = NULL;
8033 rsurface.batchelement3i_bufferoffset = 0;
8034 rsurface.batchelement3s = NULL;
8035 rsurface.batchelement3s_indexbuffer = NULL;
8036 rsurface.batchelement3s_bufferoffset = 0;
8037 rsurface.passcolor4f = NULL;
8038 rsurface.passcolor4f_vertexbuffer = NULL;
8039 rsurface.passcolor4f_bufferoffset = 0;
8042 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)
8044 rsurface.entity = r_refdef.scene.worldentity;
8045 rsurface.skeleton = NULL;
8046 rsurface.ent_skinnum = 0;
8047 rsurface.ent_qwskin = -1;
8048 rsurface.ent_shadertime = shadertime;
8049 rsurface.ent_flags = entflags;
8050 rsurface.modelnumvertices = numvertices;
8051 rsurface.modelnumtriangles = numtriangles;
8052 rsurface.matrix = *matrix;
8053 rsurface.inversematrix = *inversematrix;
8054 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8055 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8056 R_EntityMatrix(&rsurface.matrix);
8057 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8058 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8059 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8060 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8061 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8062 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8063 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8064 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8065 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8066 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8067 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8068 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8069 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);
8070 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8071 rsurface.frameblend[0].lerp = 1;
8072 rsurface.ent_alttextures = false;
8073 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8074 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8077 rsurface.modelvertex3f = (float *)vertex3f;
8078 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8079 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8080 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8082 else if (wantnormals)
8084 rsurface.modelvertex3f = (float *)vertex3f;
8085 rsurface.modelsvector3f = NULL;
8086 rsurface.modeltvector3f = NULL;
8087 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8091 rsurface.modelvertex3f = (float *)vertex3f;
8092 rsurface.modelsvector3f = NULL;
8093 rsurface.modeltvector3f = NULL;
8094 rsurface.modelnormal3f = NULL;
8096 rsurface.modelvertexmesh = NULL;
8097 rsurface.modelvertexmeshbuffer = NULL;
8098 rsurface.modelvertex3fbuffer = NULL;
8099 rsurface.modelvertex3f_vertexbuffer = 0;
8100 rsurface.modelvertex3f_bufferoffset = 0;
8101 rsurface.modelsvector3f_vertexbuffer = 0;
8102 rsurface.modelsvector3f_bufferoffset = 0;
8103 rsurface.modeltvector3f_vertexbuffer = 0;
8104 rsurface.modeltvector3f_bufferoffset = 0;
8105 rsurface.modelnormal3f_vertexbuffer = 0;
8106 rsurface.modelnormal3f_bufferoffset = 0;
8107 rsurface.modelgeneratedvertex = true;
8108 rsurface.modellightmapcolor4f = (float *)color4f;
8109 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8110 rsurface.modellightmapcolor4f_bufferoffset = 0;
8111 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8112 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8113 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8114 rsurface.modeltexcoordlightmap2f = NULL;
8115 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8116 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8117 rsurface.modelelement3i = (int *)element3i;
8118 rsurface.modelelement3i_indexbuffer = NULL;
8119 rsurface.modelelement3i_bufferoffset = 0;
8120 rsurface.modelelement3s = (unsigned short *)element3s;
8121 rsurface.modelelement3s_indexbuffer = NULL;
8122 rsurface.modelelement3s_bufferoffset = 0;
8123 rsurface.modellightmapoffsets = NULL;
8124 rsurface.modelsurfaces = NULL;
8125 rsurface.batchgeneratedvertex = false;
8126 rsurface.batchfirstvertex = 0;
8127 rsurface.batchnumvertices = 0;
8128 rsurface.batchfirsttriangle = 0;
8129 rsurface.batchnumtriangles = 0;
8130 rsurface.batchvertex3f = NULL;
8131 rsurface.batchvertex3f_vertexbuffer = NULL;
8132 rsurface.batchvertex3f_bufferoffset = 0;
8133 rsurface.batchsvector3f = NULL;
8134 rsurface.batchsvector3f_vertexbuffer = NULL;
8135 rsurface.batchsvector3f_bufferoffset = 0;
8136 rsurface.batchtvector3f = NULL;
8137 rsurface.batchtvector3f_vertexbuffer = NULL;
8138 rsurface.batchtvector3f_bufferoffset = 0;
8139 rsurface.batchnormal3f = NULL;
8140 rsurface.batchnormal3f_vertexbuffer = NULL;
8141 rsurface.batchnormal3f_bufferoffset = 0;
8142 rsurface.batchlightmapcolor4f = NULL;
8143 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8144 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8145 rsurface.batchtexcoordtexture2f = NULL;
8146 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8147 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8148 rsurface.batchtexcoordlightmap2f = NULL;
8149 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8150 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8151 rsurface.batchvertexmesh = NULL;
8152 rsurface.batchvertexmeshbuffer = NULL;
8153 rsurface.batchvertex3fbuffer = NULL;
8154 rsurface.batchelement3i = NULL;
8155 rsurface.batchelement3i_indexbuffer = NULL;
8156 rsurface.batchelement3i_bufferoffset = 0;
8157 rsurface.batchelement3s = NULL;
8158 rsurface.batchelement3s_indexbuffer = NULL;
8159 rsurface.batchelement3s_bufferoffset = 0;
8160 rsurface.passcolor4f = NULL;
8161 rsurface.passcolor4f_vertexbuffer = NULL;
8162 rsurface.passcolor4f_bufferoffset = 0;
8164 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8166 if ((wantnormals || wanttangents) && !normal3f)
8168 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8169 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8171 if (wanttangents && !svector3f)
8173 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8174 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8175 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8180 float RSurf_FogPoint(const float *v)
8182 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8183 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8184 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8185 float FogHeightFade = r_refdef.fogheightfade;
8187 unsigned int fogmasktableindex;
8188 if (r_refdef.fogplaneviewabove)
8189 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8191 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8192 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8193 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8196 float RSurf_FogVertex(const float *v)
8198 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8199 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8200 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8201 float FogHeightFade = rsurface.fogheightfade;
8203 unsigned int fogmasktableindex;
8204 if (r_refdef.fogplaneviewabove)
8205 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8207 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8208 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8209 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8212 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8215 for (i = 0;i < numelements;i++)
8216 outelement3i[i] = inelement3i[i] + adjust;
8219 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8220 extern cvar_t gl_vbo;
8221 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8229 int surfacefirsttriangle;
8230 int surfacenumtriangles;
8231 int surfacefirstvertex;
8232 int surfaceendvertex;
8233 int surfacenumvertices;
8234 int batchnumvertices;
8235 int batchnumtriangles;
8239 qboolean dynamicvertex;
8243 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8245 q3shaderinfo_deform_t *deform;
8246 const msurface_t *surface, *firstsurface;
8247 r_vertexmesh_t *vertexmesh;
8248 if (!texturenumsurfaces)
8250 // find vertex range of this surface batch
8252 firstsurface = texturesurfacelist[0];
8253 firsttriangle = firstsurface->num_firsttriangle;
8254 batchnumvertices = 0;
8255 batchnumtriangles = 0;
8256 firstvertex = endvertex = firstsurface->num_firstvertex;
8257 for (i = 0;i < texturenumsurfaces;i++)
8259 surface = texturesurfacelist[i];
8260 if (surface != firstsurface + i)
8262 surfacefirstvertex = surface->num_firstvertex;
8263 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8264 surfacenumvertices = surface->num_vertices;
8265 surfacenumtriangles = surface->num_triangles;
8266 if (firstvertex > surfacefirstvertex)
8267 firstvertex = surfacefirstvertex;
8268 if (endvertex < surfaceendvertex)
8269 endvertex = surfaceendvertex;
8270 batchnumvertices += surfacenumvertices;
8271 batchnumtriangles += surfacenumtriangles;
8274 // we now know the vertex range used, and if there are any gaps in it
8275 rsurface.batchfirstvertex = firstvertex;
8276 rsurface.batchnumvertices = endvertex - firstvertex;
8277 rsurface.batchfirsttriangle = firsttriangle;
8278 rsurface.batchnumtriangles = batchnumtriangles;
8280 // this variable holds flags for which properties have been updated that
8281 // may require regenerating vertexmesh array...
8284 // check if any dynamic vertex processing must occur
8285 dynamicvertex = false;
8287 // if there is a chance of animated vertex colors, it's a dynamic batch
8288 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8290 dynamicvertex = true;
8291 batchneed |= BATCHNEED_NOGAPS;
8292 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8295 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8297 switch (deform->deform)
8300 case Q3DEFORM_PROJECTIONSHADOW:
8301 case Q3DEFORM_TEXT0:
8302 case Q3DEFORM_TEXT1:
8303 case Q3DEFORM_TEXT2:
8304 case Q3DEFORM_TEXT3:
8305 case Q3DEFORM_TEXT4:
8306 case Q3DEFORM_TEXT5:
8307 case Q3DEFORM_TEXT6:
8308 case Q3DEFORM_TEXT7:
8311 case Q3DEFORM_AUTOSPRITE:
8312 dynamicvertex = true;
8313 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8314 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8316 case Q3DEFORM_AUTOSPRITE2:
8317 dynamicvertex = true;
8318 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8319 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8321 case Q3DEFORM_NORMAL:
8322 dynamicvertex = true;
8323 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8324 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8327 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8328 break; // if wavefunc is a nop, ignore this transform
8329 dynamicvertex = true;
8330 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8331 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8333 case Q3DEFORM_BULGE:
8334 dynamicvertex = true;
8335 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8336 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8339 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8340 break; // if wavefunc is a nop, ignore this transform
8341 dynamicvertex = true;
8342 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8343 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8347 switch(rsurface.texture->tcgen.tcgen)
8350 case Q3TCGEN_TEXTURE:
8352 case Q3TCGEN_LIGHTMAP:
8353 dynamicvertex = true;
8354 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8355 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8357 case Q3TCGEN_VECTOR:
8358 dynamicvertex = true;
8359 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8360 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8362 case Q3TCGEN_ENVIRONMENT:
8363 dynamicvertex = true;
8364 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8365 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8368 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8370 dynamicvertex = true;
8371 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8372 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8375 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8377 dynamicvertex = true;
8378 batchneed |= BATCHNEED_NOGAPS;
8379 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8382 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8384 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8385 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8386 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8387 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8388 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8389 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8390 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8393 // when the model data has no vertex buffer (dynamic mesh), we need to
8395 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8396 batchneed |= BATCHNEED_NOGAPS;
8398 // if needsupdate, we have to do a dynamic vertex batch for sure
8399 if (needsupdate & batchneed)
8400 dynamicvertex = true;
8402 // see if we need to build vertexmesh from arrays
8403 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8404 dynamicvertex = true;
8406 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8407 // also some drivers strongly dislike firstvertex
8408 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8409 dynamicvertex = true;
8411 rsurface.batchvertex3f = rsurface.modelvertex3f;
8412 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8413 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8414 rsurface.batchsvector3f = rsurface.modelsvector3f;
8415 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8416 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8417 rsurface.batchtvector3f = rsurface.modeltvector3f;
8418 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8419 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8420 rsurface.batchnormal3f = rsurface.modelnormal3f;
8421 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8422 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8423 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8424 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8425 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8426 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8427 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8428 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8429 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8430 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8431 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8432 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8433 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8434 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8435 rsurface.batchelement3i = rsurface.modelelement3i;
8436 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8437 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8438 rsurface.batchelement3s = rsurface.modelelement3s;
8439 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8440 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8442 // if any dynamic vertex processing has to occur in software, we copy the
8443 // entire surface list together before processing to rebase the vertices
8444 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8446 // if any gaps exist and we do not have a static vertex buffer, we have to
8447 // copy the surface list together to avoid wasting upload bandwidth on the
8448 // vertices in the gaps.
8450 // if gaps exist and we have a static vertex buffer, we still have to
8451 // combine the index buffer ranges into one dynamic index buffer.
8453 // in all cases we end up with data that can be drawn in one call.
8457 // static vertex data, just set pointers...
8458 rsurface.batchgeneratedvertex = false;
8459 // if there are gaps, we want to build a combined index buffer,
8460 // otherwise use the original static buffer with an appropriate offset
8463 // build a new triangle elements array for this batch
8464 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8465 rsurface.batchfirsttriangle = 0;
8467 for (i = 0;i < texturenumsurfaces;i++)
8469 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8470 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8471 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8472 numtriangles += surfacenumtriangles;
8474 rsurface.batchelement3i_indexbuffer = NULL;
8475 rsurface.batchelement3i_bufferoffset = 0;
8476 rsurface.batchelement3s = NULL;
8477 rsurface.batchelement3s_indexbuffer = NULL;
8478 rsurface.batchelement3s_bufferoffset = 0;
8479 if (endvertex <= 65536)
8481 // make a 16bit (unsigned short) index array if possible
8482 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8483 for (i = 0;i < numtriangles*3;i++)
8484 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8490 // something needs software processing, do it for real...
8491 // we only directly handle separate array data in this case and then
8492 // generate interleaved data if needed...
8493 rsurface.batchgeneratedvertex = true;
8495 // now copy the vertex data into a combined array and make an index array
8496 // (this is what Quake3 does all the time)
8497 //if (gaps || rsurface.batchfirstvertex)
8499 rsurface.batchvertex3fbuffer = NULL;
8500 rsurface.batchvertexmesh = NULL;
8501 rsurface.batchvertexmeshbuffer = NULL;
8502 rsurface.batchvertex3f = NULL;
8503 rsurface.batchvertex3f_vertexbuffer = NULL;
8504 rsurface.batchvertex3f_bufferoffset = 0;
8505 rsurface.batchsvector3f = NULL;
8506 rsurface.batchsvector3f_vertexbuffer = NULL;
8507 rsurface.batchsvector3f_bufferoffset = 0;
8508 rsurface.batchtvector3f = NULL;
8509 rsurface.batchtvector3f_vertexbuffer = NULL;
8510 rsurface.batchtvector3f_bufferoffset = 0;
8511 rsurface.batchnormal3f = NULL;
8512 rsurface.batchnormal3f_vertexbuffer = NULL;
8513 rsurface.batchnormal3f_bufferoffset = 0;
8514 rsurface.batchlightmapcolor4f = NULL;
8515 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8516 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8517 rsurface.batchtexcoordtexture2f = NULL;
8518 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8519 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8520 rsurface.batchtexcoordlightmap2f = NULL;
8521 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8522 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8523 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8524 rsurface.batchelement3i_indexbuffer = NULL;
8525 rsurface.batchelement3i_bufferoffset = 0;
8526 rsurface.batchelement3s = NULL;
8527 rsurface.batchelement3s_indexbuffer = NULL;
8528 rsurface.batchelement3s_bufferoffset = 0;
8529 // we'll only be setting up certain arrays as needed
8530 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8531 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8532 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8533 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8534 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8535 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8536 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8538 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8539 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8541 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8542 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8543 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8544 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8545 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8546 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8549 for (i = 0;i < texturenumsurfaces;i++)
8551 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8552 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8553 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8554 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8555 // copy only the data requested
8556 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8557 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8558 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8560 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8561 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8562 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8563 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8564 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8566 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8567 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8569 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8570 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8571 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8572 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8573 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8574 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8576 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8577 numvertices += surfacenumvertices;
8578 numtriangles += surfacenumtriangles;
8581 // generate a 16bit index array as well if possible
8582 // (in general, dynamic batches fit)
8583 if (numvertices <= 65536)
8585 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8586 for (i = 0;i < numtriangles*3;i++)
8587 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8590 // since we've copied everything, the batch now starts at 0
8591 rsurface.batchfirstvertex = 0;
8592 rsurface.batchnumvertices = batchnumvertices;
8593 rsurface.batchfirsttriangle = 0;
8594 rsurface.batchnumtriangles = batchnumtriangles;
8597 // q1bsp surfaces rendered in vertex color mode have to have colors
8598 // calculated based on lightstyles
8599 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8601 // generate color arrays for the surfaces in this list
8606 const unsigned char *lm;
8607 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8608 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8609 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8611 for (i = 0;i < texturenumsurfaces;i++)
8613 surface = texturesurfacelist[i];
8614 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8615 surfacenumvertices = surface->num_vertices;
8616 if (surface->lightmapinfo->samples)
8618 for (j = 0;j < surfacenumvertices;j++)
8620 lm = surface->lightmapinfo->samples + offsets[j];
8621 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8622 VectorScale(lm, scale, c);
8623 if (surface->lightmapinfo->styles[1] != 255)
8625 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8627 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8628 VectorMA(c, scale, lm, c);
8629 if (surface->lightmapinfo->styles[2] != 255)
8632 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8633 VectorMA(c, scale, lm, c);
8634 if (surface->lightmapinfo->styles[3] != 255)
8637 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8638 VectorMA(c, scale, lm, c);
8645 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);
8651 for (j = 0;j < surfacenumvertices;j++)
8653 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8660 // if vertices are deformed (sprite flares and things in maps, possibly
8661 // water waves, bulges and other deformations), modify the copied vertices
8663 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8665 switch (deform->deform)
8668 case Q3DEFORM_PROJECTIONSHADOW:
8669 case Q3DEFORM_TEXT0:
8670 case Q3DEFORM_TEXT1:
8671 case Q3DEFORM_TEXT2:
8672 case Q3DEFORM_TEXT3:
8673 case Q3DEFORM_TEXT4:
8674 case Q3DEFORM_TEXT5:
8675 case Q3DEFORM_TEXT6:
8676 case Q3DEFORM_TEXT7:
8679 case Q3DEFORM_AUTOSPRITE:
8680 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8681 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8682 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8683 VectorNormalize(newforward);
8684 VectorNormalize(newright);
8685 VectorNormalize(newup);
8686 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8687 // rsurface.batchvertex3f_vertexbuffer = NULL;
8688 // rsurface.batchvertex3f_bufferoffset = 0;
8689 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8690 // rsurface.batchsvector3f_vertexbuffer = NULL;
8691 // rsurface.batchsvector3f_bufferoffset = 0;
8692 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8693 // rsurface.batchtvector3f_vertexbuffer = NULL;
8694 // rsurface.batchtvector3f_bufferoffset = 0;
8695 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8696 // rsurface.batchnormal3f_vertexbuffer = NULL;
8697 // rsurface.batchnormal3f_bufferoffset = 0;
8698 // a single autosprite surface can contain multiple sprites...
8699 for (j = 0;j < batchnumvertices - 3;j += 4)
8701 VectorClear(center);
8702 for (i = 0;i < 4;i++)
8703 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8704 VectorScale(center, 0.25f, center);
8705 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8706 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8707 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8708 for (i = 0;i < 4;i++)
8710 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8711 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8714 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8715 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8716 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);
8718 case Q3DEFORM_AUTOSPRITE2:
8719 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8720 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8721 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8722 VectorNormalize(newforward);
8723 VectorNormalize(newright);
8724 VectorNormalize(newup);
8725 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8726 // rsurface.batchvertex3f_vertexbuffer = NULL;
8727 // rsurface.batchvertex3f_bufferoffset = 0;
8729 const float *v1, *v2;
8739 memset(shortest, 0, sizeof(shortest));
8740 // a single autosprite surface can contain multiple sprites...
8741 for (j = 0;j < batchnumvertices - 3;j += 4)
8743 VectorClear(center);
8744 for (i = 0;i < 4;i++)
8745 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8746 VectorScale(center, 0.25f, center);
8747 // find the two shortest edges, then use them to define the
8748 // axis vectors for rotating around the central axis
8749 for (i = 0;i < 6;i++)
8751 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8752 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8753 l = VectorDistance2(v1, v2);
8754 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8756 l += (1.0f / 1024.0f);
8757 if (shortest[0].length2 > l || i == 0)
8759 shortest[1] = shortest[0];
8760 shortest[0].length2 = l;
8761 shortest[0].v1 = v1;
8762 shortest[0].v2 = v2;
8764 else if (shortest[1].length2 > l || i == 1)
8766 shortest[1].length2 = l;
8767 shortest[1].v1 = v1;
8768 shortest[1].v2 = v2;
8771 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8772 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8773 // this calculates the right vector from the shortest edge
8774 // and the up vector from the edge midpoints
8775 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8776 VectorNormalize(right);
8777 VectorSubtract(end, start, up);
8778 VectorNormalize(up);
8779 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8780 VectorSubtract(rsurface.localvieworigin, center, forward);
8781 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8782 VectorNegate(forward, forward);
8783 VectorReflect(forward, 0, up, forward);
8784 VectorNormalize(forward);
8785 CrossProduct(up, forward, newright);
8786 VectorNormalize(newright);
8787 // rotate the quad around the up axis vector, this is made
8788 // especially easy by the fact we know the quad is flat,
8789 // so we only have to subtract the center position and
8790 // measure distance along the right vector, and then
8791 // multiply that by the newright vector and add back the
8793 // we also need to subtract the old position to undo the
8794 // displacement from the center, which we do with a
8795 // DotProduct, the subtraction/addition of center is also
8796 // optimized into DotProducts here
8797 l = DotProduct(right, center);
8798 for (i = 0;i < 4;i++)
8800 v1 = rsurface.batchvertex3f + 3*(j+i);
8801 f = DotProduct(right, v1) - l;
8802 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8806 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8808 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8809 // rsurface.batchnormal3f_vertexbuffer = NULL;
8810 // rsurface.batchnormal3f_bufferoffset = 0;
8811 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8813 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8815 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8816 // rsurface.batchsvector3f_vertexbuffer = NULL;
8817 // rsurface.batchsvector3f_bufferoffset = 0;
8818 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8819 // rsurface.batchtvector3f_vertexbuffer = NULL;
8820 // rsurface.batchtvector3f_bufferoffset = 0;
8821 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);
8824 case Q3DEFORM_NORMAL:
8825 // deform the normals to make reflections wavey
8826 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8827 rsurface.batchnormal3f_vertexbuffer = NULL;
8828 rsurface.batchnormal3f_bufferoffset = 0;
8829 for (j = 0;j < batchnumvertices;j++)
8832 float *normal = rsurface.batchnormal3f + 3*j;
8833 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8834 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8835 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]);
8836 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]);
8837 VectorNormalize(normal);
8839 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8841 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8842 // rsurface.batchsvector3f_vertexbuffer = NULL;
8843 // rsurface.batchsvector3f_bufferoffset = 0;
8844 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8845 // rsurface.batchtvector3f_vertexbuffer = NULL;
8846 // rsurface.batchtvector3f_bufferoffset = 0;
8847 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);
8851 // deform vertex array to make wavey water and flags and such
8852 waveparms[0] = deform->waveparms[0];
8853 waveparms[1] = deform->waveparms[1];
8854 waveparms[2] = deform->waveparms[2];
8855 waveparms[3] = deform->waveparms[3];
8856 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8857 break; // if wavefunc is a nop, don't make a dynamic vertex array
8858 // this is how a divisor of vertex influence on deformation
8859 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8860 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8861 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8862 // rsurface.batchvertex3f_vertexbuffer = NULL;
8863 // rsurface.batchvertex3f_bufferoffset = 0;
8864 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8865 // rsurface.batchnormal3f_vertexbuffer = NULL;
8866 // rsurface.batchnormal3f_bufferoffset = 0;
8867 for (j = 0;j < batchnumvertices;j++)
8869 // if the wavefunc depends on time, evaluate it per-vertex
8872 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8873 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8875 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8877 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8878 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8879 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8881 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8882 // rsurface.batchsvector3f_vertexbuffer = NULL;
8883 // rsurface.batchsvector3f_bufferoffset = 0;
8884 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8885 // rsurface.batchtvector3f_vertexbuffer = NULL;
8886 // rsurface.batchtvector3f_bufferoffset = 0;
8887 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);
8890 case Q3DEFORM_BULGE:
8891 // deform vertex array to make the surface have moving bulges
8892 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8893 // rsurface.batchvertex3f_vertexbuffer = NULL;
8894 // rsurface.batchvertex3f_bufferoffset = 0;
8895 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8896 // rsurface.batchnormal3f_vertexbuffer = NULL;
8897 // rsurface.batchnormal3f_bufferoffset = 0;
8898 for (j = 0;j < batchnumvertices;j++)
8900 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8901 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8903 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8904 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8905 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8907 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8908 // rsurface.batchsvector3f_vertexbuffer = NULL;
8909 // rsurface.batchsvector3f_bufferoffset = 0;
8910 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8911 // rsurface.batchtvector3f_vertexbuffer = NULL;
8912 // rsurface.batchtvector3f_bufferoffset = 0;
8913 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);
8917 // deform vertex array
8918 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8919 break; // if wavefunc is a nop, don't make a dynamic vertex array
8920 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8921 VectorScale(deform->parms, scale, waveparms);
8922 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8923 // rsurface.batchvertex3f_vertexbuffer = NULL;
8924 // rsurface.batchvertex3f_bufferoffset = 0;
8925 for (j = 0;j < batchnumvertices;j++)
8926 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8931 // generate texcoords based on the chosen texcoord source
8932 switch(rsurface.texture->tcgen.tcgen)
8935 case Q3TCGEN_TEXTURE:
8937 case Q3TCGEN_LIGHTMAP:
8938 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8939 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8940 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8941 if (rsurface.batchtexcoordlightmap2f)
8942 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8944 case Q3TCGEN_VECTOR:
8945 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8946 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8947 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8948 for (j = 0;j < batchnumvertices;j++)
8950 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8951 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8954 case Q3TCGEN_ENVIRONMENT:
8955 // make environment reflections using a spheremap
8956 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8957 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8958 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8959 for (j = 0;j < batchnumvertices;j++)
8961 // identical to Q3A's method, but executed in worldspace so
8962 // carried models can be shiny too
8964 float viewer[3], d, reflected[3], worldreflected[3];
8966 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8967 // VectorNormalize(viewer);
8969 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8971 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8972 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8973 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8974 // note: this is proportinal to viewer, so we can normalize later
8976 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8977 VectorNormalize(worldreflected);
8979 // note: this sphere map only uses world x and z!
8980 // so positive and negative y will LOOK THE SAME.
8981 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8982 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8986 // the only tcmod that needs software vertex processing is turbulent, so
8987 // check for it here and apply the changes if needed
8988 // and we only support that as the first one
8989 // (handling a mixture of turbulent and other tcmods would be problematic
8990 // without punting it entirely to a software path)
8991 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8993 amplitude = rsurface.texture->tcmods[0].parms[1];
8994 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8995 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8996 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8997 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8998 for (j = 0;j < batchnumvertices;j++)
9000 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);
9001 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9005 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9007 // convert the modified arrays to vertex structs
9008 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9009 // rsurface.batchvertexmeshbuffer = NULL;
9010 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9011 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9012 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9013 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9014 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9015 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9016 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9018 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9020 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9021 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9024 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9025 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9026 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9027 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9028 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9029 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9030 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9031 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9032 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9036 void RSurf_DrawBatch(void)
9038 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9039 // through the pipeline, killing it earlier in the pipeline would have
9040 // per-surface overhead rather than per-batch overhead, so it's best to
9041 // reject it here, before it hits glDraw.
9042 if (rsurface.batchnumtriangles == 0)
9045 // batch debugging code
9046 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9052 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9053 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9056 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9058 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9060 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9061 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);
9068 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);
9071 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9073 // pick the closest matching water plane
9074 int planeindex, vertexindex, bestplaneindex = -1;
9078 r_waterstate_waterplane_t *p;
9079 qboolean prepared = false;
9081 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9083 if(p->camera_entity != rsurface.texture->camera_entity)
9088 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9090 if(rsurface.batchnumvertices == 0)
9093 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9095 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9096 d += fabs(PlaneDiff(vert, &p->plane));
9098 if (bestd > d || bestplaneindex < 0)
9101 bestplaneindex = planeindex;
9104 return bestplaneindex;
9105 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9106 // this situation though, as it might be better to render single larger
9107 // batches with useless stuff (backface culled for example) than to
9108 // render multiple smaller batches
9111 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9114 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9115 rsurface.passcolor4f_vertexbuffer = 0;
9116 rsurface.passcolor4f_bufferoffset = 0;
9117 for (i = 0;i < rsurface.batchnumvertices;i++)
9118 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9121 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9128 if (rsurface.passcolor4f)
9130 // generate color arrays
9131 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9132 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9133 rsurface.passcolor4f_vertexbuffer = 0;
9134 rsurface.passcolor4f_bufferoffset = 0;
9135 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)
9137 f = RSurf_FogVertex(v);
9146 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9147 rsurface.passcolor4f_vertexbuffer = 0;
9148 rsurface.passcolor4f_bufferoffset = 0;
9149 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9151 f = RSurf_FogVertex(v);
9160 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9167 if (!rsurface.passcolor4f)
9169 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9170 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9171 rsurface.passcolor4f_vertexbuffer = 0;
9172 rsurface.passcolor4f_bufferoffset = 0;
9173 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)
9175 f = RSurf_FogVertex(v);
9176 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9177 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9178 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9183 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9188 if (!rsurface.passcolor4f)
9190 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9191 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9192 rsurface.passcolor4f_vertexbuffer = 0;
9193 rsurface.passcolor4f_bufferoffset = 0;
9194 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9203 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9208 if (!rsurface.passcolor4f)
9210 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9211 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9212 rsurface.passcolor4f_vertexbuffer = 0;
9213 rsurface.passcolor4f_bufferoffset = 0;
9214 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9216 c2[0] = c[0] + r_refdef.scene.ambient;
9217 c2[1] = c[1] + r_refdef.scene.ambient;
9218 c2[2] = c[2] + r_refdef.scene.ambient;
9223 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9226 rsurface.passcolor4f = NULL;
9227 rsurface.passcolor4f_vertexbuffer = 0;
9228 rsurface.passcolor4f_bufferoffset = 0;
9229 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9230 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9231 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9232 GL_Color(r, g, b, a);
9233 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9237 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9239 // TODO: optimize applyfog && applycolor case
9240 // just apply fog if necessary, and tint the fog color array if necessary
9241 rsurface.passcolor4f = NULL;
9242 rsurface.passcolor4f_vertexbuffer = 0;
9243 rsurface.passcolor4f_bufferoffset = 0;
9244 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9245 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9246 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9247 GL_Color(r, g, b, a);
9251 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9254 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9255 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9256 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9257 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9258 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9259 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9260 GL_Color(r, g, b, a);
9264 static void RSurf_DrawBatch_GL11_ClampColor(void)
9269 if (!rsurface.passcolor4f)
9271 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9273 c2[0] = bound(0.0f, c1[0], 1.0f);
9274 c2[1] = bound(0.0f, c1[1], 1.0f);
9275 c2[2] = bound(0.0f, c1[2], 1.0f);
9276 c2[3] = bound(0.0f, c1[3], 1.0f);
9280 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9290 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9291 rsurface.passcolor4f_vertexbuffer = 0;
9292 rsurface.passcolor4f_bufferoffset = 0;
9293 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)
9295 f = -DotProduct(r_refdef.view.forward, n);
9297 f = f * 0.85 + 0.15; // work around so stuff won't get black
9298 f *= r_refdef.lightmapintensity;
9299 Vector4Set(c, f, f, f, 1);
9303 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9305 RSurf_DrawBatch_GL11_ApplyFakeLight();
9306 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9307 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9308 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9309 GL_Color(r, g, b, a);
9313 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9321 vec3_t ambientcolor;
9322 vec3_t diffusecolor;
9326 VectorCopy(rsurface.modellight_lightdir, lightdir);
9327 f = 0.5f * r_refdef.lightmapintensity;
9328 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9329 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9330 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9331 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9332 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9333 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9335 if (VectorLength2(diffusecolor) > 0)
9337 // q3-style directional shading
9338 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9339 rsurface.passcolor4f_vertexbuffer = 0;
9340 rsurface.passcolor4f_bufferoffset = 0;
9341 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)
9343 if ((f = DotProduct(n, lightdir)) > 0)
9344 VectorMA(ambientcolor, f, diffusecolor, c);
9346 VectorCopy(ambientcolor, c);
9353 *applycolor = false;
9357 *r = ambientcolor[0];
9358 *g = ambientcolor[1];
9359 *b = ambientcolor[2];
9360 rsurface.passcolor4f = NULL;
9361 rsurface.passcolor4f_vertexbuffer = 0;
9362 rsurface.passcolor4f_bufferoffset = 0;
9366 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9368 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9369 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9370 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9371 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9372 GL_Color(r, g, b, a);
9376 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9384 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9385 rsurface.passcolor4f_vertexbuffer = 0;
9386 rsurface.passcolor4f_bufferoffset = 0;
9388 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9390 f = 1 - RSurf_FogVertex(v);
9398 void RSurf_SetupDepthAndCulling(void)
9400 // submodels are biased to avoid z-fighting with world surfaces that they
9401 // may be exactly overlapping (avoids z-fighting artifacts on certain
9402 // doors and things in Quake maps)
9403 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9404 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9405 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9406 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9409 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9411 // transparent sky would be ridiculous
9412 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9414 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9415 skyrenderlater = true;
9416 RSurf_SetupDepthAndCulling();
9418 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9419 // skymasking on them, and Quake3 never did sky masking (unlike
9420 // software Quake and software Quake2), so disable the sky masking
9421 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9422 // and skymasking also looks very bad when noclipping outside the
9423 // level, so don't use it then either.
9424 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9426 R_Mesh_ResetTextureState();
9427 if (skyrendermasked)
9429 R_SetupShader_DepthOrShadow();
9430 // depth-only (masking)
9431 GL_ColorMask(0,0,0,0);
9432 // just to make sure that braindead drivers don't draw
9433 // anything despite that colormask...
9434 GL_BlendFunc(GL_ZERO, GL_ONE);
9435 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9436 if (rsurface.batchvertex3fbuffer)
9437 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9439 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9443 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9445 GL_BlendFunc(GL_ONE, GL_ZERO);
9446 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9447 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9448 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9451 if (skyrendermasked)
9452 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9454 R_Mesh_ResetTextureState();
9455 GL_Color(1, 1, 1, 1);
9458 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9459 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9460 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9462 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9466 // render screenspace normalmap to texture
9468 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9473 // bind lightmap texture
9475 // water/refraction/reflection/camera surfaces have to be handled specially
9476 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9478 int start, end, startplaneindex;
9479 for (start = 0;start < texturenumsurfaces;start = end)
9481 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9482 if(startplaneindex < 0)
9484 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9485 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9489 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9491 // now that we have a batch using the same planeindex, render it
9492 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9494 // render water or distortion background
9496 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));
9498 // blend surface on top
9499 GL_DepthMask(false);
9500 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9503 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9505 // render surface with reflection texture as input
9506 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9507 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));
9514 // render surface batch normally
9515 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9516 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9520 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9522 // OpenGL 1.3 path - anything not completely ancient
9523 qboolean applycolor;
9526 const texturelayer_t *layer;
9527 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);
9528 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9530 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9533 int layertexrgbscale;
9534 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9536 if (layerindex == 0)
9540 GL_AlphaTest(false);
9541 GL_DepthFunc(GL_EQUAL);
9544 GL_DepthMask(layer->depthmask && writedepth);
9545 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9546 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9548 layertexrgbscale = 4;
9549 VectorScale(layer->color, 0.25f, layercolor);
9551 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9553 layertexrgbscale = 2;
9554 VectorScale(layer->color, 0.5f, layercolor);
9558 layertexrgbscale = 1;
9559 VectorScale(layer->color, 1.0f, layercolor);
9561 layercolor[3] = layer->color[3];
9562 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9563 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9564 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9565 switch (layer->type)
9567 case TEXTURELAYERTYPE_LITTEXTURE:
9568 // single-pass lightmapped texture with 2x rgbscale
9569 R_Mesh_TexBind(0, r_texture_white);
9570 R_Mesh_TexMatrix(0, NULL);
9571 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9572 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9573 R_Mesh_TexBind(1, layer->texture);
9574 R_Mesh_TexMatrix(1, &layer->texmatrix);
9575 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9576 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9577 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9578 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9579 else if (FAKELIGHT_ENABLED)
9580 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9581 else if (rsurface.uselightmaptexture)
9582 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9584 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9586 case TEXTURELAYERTYPE_TEXTURE:
9587 // singletexture unlit texture with transparency support
9588 R_Mesh_TexBind(0, layer->texture);
9589 R_Mesh_TexMatrix(0, &layer->texmatrix);
9590 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9591 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9592 R_Mesh_TexBind(1, 0);
9593 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9594 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9596 case TEXTURELAYERTYPE_FOG:
9597 // singletexture fogging
9600 R_Mesh_TexBind(0, layer->texture);
9601 R_Mesh_TexMatrix(0, &layer->texmatrix);
9602 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9603 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9607 R_Mesh_TexBind(0, 0);
9608 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9610 R_Mesh_TexBind(1, 0);
9611 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9612 // generate a color array for the fog pass
9613 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9614 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9618 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9621 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9623 GL_DepthFunc(GL_LEQUAL);
9624 GL_AlphaTest(false);
9628 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9630 // OpenGL 1.1 - crusty old voodoo path
9633 const texturelayer_t *layer;
9634 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);
9635 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9637 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9639 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9641 if (layerindex == 0)
9645 GL_AlphaTest(false);
9646 GL_DepthFunc(GL_EQUAL);
9649 GL_DepthMask(layer->depthmask && writedepth);
9650 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9651 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9652 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9653 switch (layer->type)
9655 case TEXTURELAYERTYPE_LITTEXTURE:
9656 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9658 // two-pass lit texture with 2x rgbscale
9659 // first the lightmap pass
9660 R_Mesh_TexBind(0, r_texture_white);
9661 R_Mesh_TexMatrix(0, NULL);
9662 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9663 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9664 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9665 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9666 else if (FAKELIGHT_ENABLED)
9667 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9668 else if (rsurface.uselightmaptexture)
9669 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9671 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9672 // then apply the texture to it
9673 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9674 R_Mesh_TexBind(0, layer->texture);
9675 R_Mesh_TexMatrix(0, &layer->texmatrix);
9676 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9677 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9678 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);
9682 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9683 R_Mesh_TexBind(0, layer->texture);
9684 R_Mesh_TexMatrix(0, &layer->texmatrix);
9685 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9686 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9687 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9688 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);
9690 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);
9693 case TEXTURELAYERTYPE_TEXTURE:
9694 // singletexture unlit texture with transparency support
9695 R_Mesh_TexBind(0, layer->texture);
9696 R_Mesh_TexMatrix(0, &layer->texmatrix);
9697 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9698 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9699 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);
9701 case TEXTURELAYERTYPE_FOG:
9702 // singletexture fogging
9705 R_Mesh_TexBind(0, layer->texture);
9706 R_Mesh_TexMatrix(0, &layer->texmatrix);
9707 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9708 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9712 R_Mesh_TexBind(0, 0);
9713 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9715 // generate a color array for the fog pass
9716 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9717 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9721 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9724 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9726 GL_DepthFunc(GL_LEQUAL);
9727 GL_AlphaTest(false);
9731 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9735 r_vertexgeneric_t *batchvertex;
9738 // R_Mesh_ResetTextureState();
9739 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9741 if(rsurface.texture && rsurface.texture->currentskinframe)
9743 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9744 c[3] *= rsurface.texture->currentalpha;
9754 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9756 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9757 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9758 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9761 // brighten it up (as texture value 127 means "unlit")
9762 c[0] *= 2 * r_refdef.view.colorscale;
9763 c[1] *= 2 * r_refdef.view.colorscale;
9764 c[2] *= 2 * r_refdef.view.colorscale;
9766 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9767 c[3] *= r_wateralpha.value;
9769 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9771 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9772 GL_DepthMask(false);
9774 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9776 GL_BlendFunc(GL_ONE, GL_ONE);
9777 GL_DepthMask(false);
9779 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9781 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9782 GL_DepthMask(false);
9784 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9786 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9787 GL_DepthMask(false);
9791 GL_BlendFunc(GL_ONE, GL_ZERO);
9792 GL_DepthMask(writedepth);
9795 if (r_showsurfaces.integer == 3)
9797 rsurface.passcolor4f = NULL;
9799 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9801 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9803 rsurface.passcolor4f = NULL;
9804 rsurface.passcolor4f_vertexbuffer = 0;
9805 rsurface.passcolor4f_bufferoffset = 0;
9807 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9809 qboolean applycolor = true;
9812 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9814 r_refdef.lightmapintensity = 1;
9815 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9816 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9818 else if (FAKELIGHT_ENABLED)
9820 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9822 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9823 RSurf_DrawBatch_GL11_ApplyFakeLight();
9824 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9828 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9830 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9831 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9832 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9835 if(!rsurface.passcolor4f)
9836 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9838 RSurf_DrawBatch_GL11_ApplyAmbient();
9839 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9840 if(r_refdef.fogenabled)
9841 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9842 RSurf_DrawBatch_GL11_ClampColor();
9844 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9845 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9848 else if (!r_refdef.view.showdebug)
9850 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9851 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9852 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9854 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9855 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9857 R_Mesh_PrepareVertices_Generic_Unlock();
9860 else if (r_showsurfaces.integer == 4)
9862 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9863 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9864 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9866 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9867 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9868 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9870 R_Mesh_PrepareVertices_Generic_Unlock();
9873 else if (r_showsurfaces.integer == 2)
9876 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9877 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9878 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9880 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9881 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9882 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9883 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9884 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9885 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9886 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9888 R_Mesh_PrepareVertices_Generic_Unlock();
9889 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9893 int texturesurfaceindex;
9895 const msurface_t *surface;
9896 float surfacecolor4f[4];
9897 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9898 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9900 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9902 surface = texturesurfacelist[texturesurfaceindex];
9903 k = (int)(((size_t)surface) / sizeof(msurface_t));
9904 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9905 for (j = 0;j < surface->num_vertices;j++)
9907 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9908 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9912 R_Mesh_PrepareVertices_Generic_Unlock();
9917 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9920 RSurf_SetupDepthAndCulling();
9921 if (r_showsurfaces.integer)
9923 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9926 switch (vid.renderpath)
9928 case RENDERPATH_GL20:
9929 case RENDERPATH_D3D9:
9930 case RENDERPATH_D3D10:
9931 case RENDERPATH_D3D11:
9932 case RENDERPATH_SOFT:
9933 case RENDERPATH_GLES2:
9934 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9936 case RENDERPATH_GL13:
9937 case RENDERPATH_GLES1:
9938 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9940 case RENDERPATH_GL11:
9941 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9947 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9950 RSurf_SetupDepthAndCulling();
9951 if (r_showsurfaces.integer)
9953 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9956 switch (vid.renderpath)
9958 case RENDERPATH_GL20:
9959 case RENDERPATH_D3D9:
9960 case RENDERPATH_D3D10:
9961 case RENDERPATH_D3D11:
9962 case RENDERPATH_SOFT:
9963 case RENDERPATH_GLES2:
9964 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9966 case RENDERPATH_GL13:
9967 case RENDERPATH_GLES1:
9968 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9970 case RENDERPATH_GL11:
9971 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9977 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9980 int texturenumsurfaces, endsurface;
9982 const msurface_t *surface;
9983 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9985 // if the model is static it doesn't matter what value we give for
9986 // wantnormals and wanttangents, so this logic uses only rules applicable
9987 // to a model, knowing that they are meaningless otherwise
9988 if (ent == r_refdef.scene.worldentity)
9989 RSurf_ActiveWorldEntity();
9990 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9991 RSurf_ActiveModelEntity(ent, false, false, false);
9994 switch (vid.renderpath)
9996 case RENDERPATH_GL20:
9997 case RENDERPATH_D3D9:
9998 case RENDERPATH_D3D10:
9999 case RENDERPATH_D3D11:
10000 case RENDERPATH_SOFT:
10001 case RENDERPATH_GLES2:
10002 RSurf_ActiveModelEntity(ent, true, true, false);
10004 case RENDERPATH_GL11:
10005 case RENDERPATH_GL13:
10006 case RENDERPATH_GLES1:
10007 RSurf_ActiveModelEntity(ent, true, false, false);
10012 if (r_transparentdepthmasking.integer)
10014 qboolean setup = false;
10015 for (i = 0;i < numsurfaces;i = j)
10018 surface = rsurface.modelsurfaces + surfacelist[i];
10019 texture = surface->texture;
10020 rsurface.texture = R_GetCurrentTexture(texture);
10021 rsurface.lightmaptexture = NULL;
10022 rsurface.deluxemaptexture = NULL;
10023 rsurface.uselightmaptexture = false;
10024 // scan ahead until we find a different texture
10025 endsurface = min(i + 1024, numsurfaces);
10026 texturenumsurfaces = 0;
10027 texturesurfacelist[texturenumsurfaces++] = surface;
10028 for (;j < endsurface;j++)
10030 surface = rsurface.modelsurfaces + surfacelist[j];
10031 if (texture != surface->texture)
10033 texturesurfacelist[texturenumsurfaces++] = surface;
10035 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10037 // render the range of surfaces as depth
10041 GL_ColorMask(0,0,0,0);
10043 GL_DepthTest(true);
10044 GL_BlendFunc(GL_ONE, GL_ZERO);
10045 GL_DepthMask(true);
10046 // R_Mesh_ResetTextureState();
10047 R_SetupShader_DepthOrShadow();
10049 RSurf_SetupDepthAndCulling();
10050 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10051 if (rsurface.batchvertex3fbuffer)
10052 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10054 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10058 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10061 for (i = 0;i < numsurfaces;i = j)
10064 surface = rsurface.modelsurfaces + surfacelist[i];
10065 texture = surface->texture;
10066 rsurface.texture = R_GetCurrentTexture(texture);
10067 // scan ahead until we find a different texture
10068 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10069 texturenumsurfaces = 0;
10070 texturesurfacelist[texturenumsurfaces++] = surface;
10071 if(FAKELIGHT_ENABLED)
10073 rsurface.lightmaptexture = NULL;
10074 rsurface.deluxemaptexture = NULL;
10075 rsurface.uselightmaptexture = false;
10076 for (;j < endsurface;j++)
10078 surface = rsurface.modelsurfaces + surfacelist[j];
10079 if (texture != surface->texture)
10081 texturesurfacelist[texturenumsurfaces++] = surface;
10086 rsurface.lightmaptexture = surface->lightmaptexture;
10087 rsurface.deluxemaptexture = surface->deluxemaptexture;
10088 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10089 for (;j < endsurface;j++)
10091 surface = rsurface.modelsurfaces + surfacelist[j];
10092 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10094 texturesurfacelist[texturenumsurfaces++] = surface;
10097 // render the range of surfaces
10098 if (ent == r_refdef.scene.worldentity)
10099 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10101 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10103 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10106 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10108 // transparent surfaces get pushed off into the transparent queue
10109 int surfacelistindex;
10110 const msurface_t *surface;
10111 vec3_t tempcenter, center;
10112 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10114 surface = texturesurfacelist[surfacelistindex];
10115 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10116 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10117 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10118 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10119 if (queueentity->transparent_offset) // transparent offset
10121 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10122 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10123 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10125 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10129 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10131 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10133 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10135 RSurf_SetupDepthAndCulling();
10136 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10137 if (rsurface.batchvertex3fbuffer)
10138 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10140 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10144 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10146 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10149 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10152 if (!rsurface.texture->currentnumlayers)
10154 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10155 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10157 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10159 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10160 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10161 else if (!rsurface.texture->currentnumlayers)
10163 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10165 // in the deferred case, transparent surfaces were queued during prepass
10166 if (!r_shadow_usingdeferredprepass)
10167 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10171 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10172 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10177 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10180 texture_t *texture;
10181 R_FrameData_SetMark();
10182 // break the surface list down into batches by texture and use of lightmapping
10183 for (i = 0;i < numsurfaces;i = j)
10186 // texture is the base texture pointer, rsurface.texture is the
10187 // current frame/skin the texture is directing us to use (for example
10188 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10189 // use skin 1 instead)
10190 texture = surfacelist[i]->texture;
10191 rsurface.texture = R_GetCurrentTexture(texture);
10192 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10194 // if this texture is not the kind we want, skip ahead to the next one
10195 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10199 if(FAKELIGHT_ENABLED || depthonly || prepass)
10201 rsurface.lightmaptexture = NULL;
10202 rsurface.deluxemaptexture = NULL;
10203 rsurface.uselightmaptexture = false;
10204 // simply scan ahead until we find a different texture or lightmap state
10205 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10210 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10211 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10212 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10213 // simply scan ahead until we find a different texture or lightmap state
10214 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10217 // render the range of surfaces
10218 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10220 R_FrameData_ReturnToMark();
10223 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10227 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10230 if (!rsurface.texture->currentnumlayers)
10232 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10233 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10235 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10237 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10238 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10239 else if (!rsurface.texture->currentnumlayers)
10241 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10243 // in the deferred case, transparent surfaces were queued during prepass
10244 if (!r_shadow_usingdeferredprepass)
10245 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10249 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10250 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10255 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10258 texture_t *texture;
10259 R_FrameData_SetMark();
10260 // break the surface list down into batches by texture and use of lightmapping
10261 for (i = 0;i < numsurfaces;i = j)
10264 // texture is the base texture pointer, rsurface.texture is the
10265 // current frame/skin the texture is directing us to use (for example
10266 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10267 // use skin 1 instead)
10268 texture = surfacelist[i]->texture;
10269 rsurface.texture = R_GetCurrentTexture(texture);
10270 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10272 // if this texture is not the kind we want, skip ahead to the next one
10273 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10277 if(FAKELIGHT_ENABLED || depthonly || prepass)
10279 rsurface.lightmaptexture = NULL;
10280 rsurface.deluxemaptexture = NULL;
10281 rsurface.uselightmaptexture = false;
10282 // simply scan ahead until we find a different texture or lightmap state
10283 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10288 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10289 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10290 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10291 // simply scan ahead until we find a different texture or lightmap state
10292 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10295 // render the range of surfaces
10296 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10298 R_FrameData_ReturnToMark();
10301 float locboxvertex3f[6*4*3] =
10303 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10304 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10305 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10306 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10307 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10308 1,0,0, 0,0,0, 0,1,0, 1,1,0
10311 unsigned short locboxelements[6*2*3] =
10316 12,13,14, 12,14,15,
10317 16,17,18, 16,18,19,
10321 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10324 cl_locnode_t *loc = (cl_locnode_t *)ent;
10326 float vertex3f[6*4*3];
10328 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10329 GL_DepthMask(false);
10330 GL_DepthRange(0, 1);
10331 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10332 GL_DepthTest(true);
10333 GL_CullFace(GL_NONE);
10334 R_EntityMatrix(&identitymatrix);
10336 // R_Mesh_ResetTextureState();
10338 i = surfacelist[0];
10339 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10340 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10341 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10342 surfacelist[0] < 0 ? 0.5f : 0.125f);
10344 if (VectorCompare(loc->mins, loc->maxs))
10346 VectorSet(size, 2, 2, 2);
10347 VectorMA(loc->mins, -0.5f, size, mins);
10351 VectorCopy(loc->mins, mins);
10352 VectorSubtract(loc->maxs, loc->mins, size);
10355 for (i = 0;i < 6*4*3;)
10356 for (j = 0;j < 3;j++, i++)
10357 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10359 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10360 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10361 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10364 void R_DrawLocs(void)
10367 cl_locnode_t *loc, *nearestloc;
10369 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10370 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10372 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10373 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10377 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10379 if (decalsystem->decals)
10380 Mem_Free(decalsystem->decals);
10381 memset(decalsystem, 0, sizeof(*decalsystem));
10384 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)
10387 tridecal_t *decals;
10390 // expand or initialize the system
10391 if (decalsystem->maxdecals <= decalsystem->numdecals)
10393 decalsystem_t old = *decalsystem;
10394 qboolean useshortelements;
10395 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10396 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10397 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)));
10398 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10399 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10400 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10401 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10402 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10403 if (decalsystem->numdecals)
10404 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10406 Mem_Free(old.decals);
10407 for (i = 0;i < decalsystem->maxdecals*3;i++)
10408 decalsystem->element3i[i] = i;
10409 if (useshortelements)
10410 for (i = 0;i < decalsystem->maxdecals*3;i++)
10411 decalsystem->element3s[i] = i;
10414 // grab a decal and search for another free slot for the next one
10415 decals = decalsystem->decals;
10416 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10417 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10419 decalsystem->freedecal = i;
10420 if (decalsystem->numdecals <= i)
10421 decalsystem->numdecals = i + 1;
10423 // initialize the decal
10425 decal->triangleindex = triangleindex;
10426 decal->surfaceindex = surfaceindex;
10427 decal->decalsequence = decalsequence;
10428 decal->color4f[0][0] = c0[0];
10429 decal->color4f[0][1] = c0[1];
10430 decal->color4f[0][2] = c0[2];
10431 decal->color4f[0][3] = 1;
10432 decal->color4f[1][0] = c1[0];
10433 decal->color4f[1][1] = c1[1];
10434 decal->color4f[1][2] = c1[2];
10435 decal->color4f[1][3] = 1;
10436 decal->color4f[2][0] = c2[0];
10437 decal->color4f[2][1] = c2[1];
10438 decal->color4f[2][2] = c2[2];
10439 decal->color4f[2][3] = 1;
10440 decal->vertex3f[0][0] = v0[0];
10441 decal->vertex3f[0][1] = v0[1];
10442 decal->vertex3f[0][2] = v0[2];
10443 decal->vertex3f[1][0] = v1[0];
10444 decal->vertex3f[1][1] = v1[1];
10445 decal->vertex3f[1][2] = v1[2];
10446 decal->vertex3f[2][0] = v2[0];
10447 decal->vertex3f[2][1] = v2[1];
10448 decal->vertex3f[2][2] = v2[2];
10449 decal->texcoord2f[0][0] = t0[0];
10450 decal->texcoord2f[0][1] = t0[1];
10451 decal->texcoord2f[1][0] = t1[0];
10452 decal->texcoord2f[1][1] = t1[1];
10453 decal->texcoord2f[2][0] = t2[0];
10454 decal->texcoord2f[2][1] = t2[1];
10455 TriangleNormal(v0, v1, v2, decal->plane);
10456 VectorNormalize(decal->plane);
10457 decal->plane[3] = DotProduct(v0, decal->plane);
10460 extern cvar_t cl_decals_bias;
10461 extern cvar_t cl_decals_models;
10462 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10463 // baseparms, parms, temps
10464 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)
10469 const float *vertex3f;
10470 const float *normal3f;
10472 float points[2][9][3];
10479 e = rsurface.modelelement3i + 3*triangleindex;
10481 vertex3f = rsurface.modelvertex3f;
10482 normal3f = rsurface.modelnormal3f;
10486 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10488 index = 3*e[cornerindex];
10489 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10494 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10496 index = 3*e[cornerindex];
10497 VectorCopy(vertex3f + index, v[cornerindex]);
10502 //TriangleNormal(v[0], v[1], v[2], normal);
10503 //if (DotProduct(normal, localnormal) < 0.0f)
10505 // clip by each of the box planes formed from the projection matrix
10506 // if anything survives, we emit the decal
10507 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]);
10510 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]);
10513 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]);
10516 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]);
10519 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]);
10522 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]);
10525 // some part of the triangle survived, so we have to accept it...
10528 // dynamic always uses the original triangle
10530 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10532 index = 3*e[cornerindex];
10533 VectorCopy(vertex3f + index, v[cornerindex]);
10536 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10538 // convert vertex positions to texcoords
10539 Matrix4x4_Transform(projection, v[cornerindex], temp);
10540 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10541 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10542 // calculate distance fade from the projection origin
10543 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10544 f = bound(0.0f, f, 1.0f);
10545 c[cornerindex][0] = r * f;
10546 c[cornerindex][1] = g * f;
10547 c[cornerindex][2] = b * f;
10548 c[cornerindex][3] = 1.0f;
10549 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10552 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);
10554 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10555 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);
10557 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)
10559 matrix4x4_t projection;
10560 decalsystem_t *decalsystem;
10563 const msurface_t *surface;
10564 const msurface_t *surfaces;
10565 const int *surfacelist;
10566 const texture_t *texture;
10568 int numsurfacelist;
10569 int surfacelistindex;
10572 float localorigin[3];
10573 float localnormal[3];
10574 float localmins[3];
10575 float localmaxs[3];
10578 float planes[6][4];
10581 int bih_triangles_count;
10582 int bih_triangles[256];
10583 int bih_surfaces[256];
10585 decalsystem = &ent->decalsystem;
10586 model = ent->model;
10587 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10589 R_DecalSystem_Reset(&ent->decalsystem);
10593 if (!model->brush.data_leafs && !cl_decals_models.integer)
10595 if (decalsystem->model)
10596 R_DecalSystem_Reset(decalsystem);
10600 if (decalsystem->model != model)
10601 R_DecalSystem_Reset(decalsystem);
10602 decalsystem->model = model;
10604 RSurf_ActiveModelEntity(ent, true, false, false);
10606 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10607 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10608 VectorNormalize(localnormal);
10609 localsize = worldsize*rsurface.inversematrixscale;
10610 localmins[0] = localorigin[0] - localsize;
10611 localmins[1] = localorigin[1] - localsize;
10612 localmins[2] = localorigin[2] - localsize;
10613 localmaxs[0] = localorigin[0] + localsize;
10614 localmaxs[1] = localorigin[1] + localsize;
10615 localmaxs[2] = localorigin[2] + localsize;
10617 //VectorCopy(localnormal, planes[4]);
10618 //VectorVectors(planes[4], planes[2], planes[0]);
10619 AnglesFromVectors(angles, localnormal, NULL, false);
10620 AngleVectors(angles, planes[0], planes[2], planes[4]);
10621 VectorNegate(planes[0], planes[1]);
10622 VectorNegate(planes[2], planes[3]);
10623 VectorNegate(planes[4], planes[5]);
10624 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10625 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10626 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10627 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10628 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10629 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10634 matrix4x4_t forwardprojection;
10635 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10636 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10641 float projectionvector[4][3];
10642 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10643 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10644 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10645 projectionvector[0][0] = planes[0][0] * ilocalsize;
10646 projectionvector[0][1] = planes[1][0] * ilocalsize;
10647 projectionvector[0][2] = planes[2][0] * ilocalsize;
10648 projectionvector[1][0] = planes[0][1] * ilocalsize;
10649 projectionvector[1][1] = planes[1][1] * ilocalsize;
10650 projectionvector[1][2] = planes[2][1] * ilocalsize;
10651 projectionvector[2][0] = planes[0][2] * ilocalsize;
10652 projectionvector[2][1] = planes[1][2] * ilocalsize;
10653 projectionvector[2][2] = planes[2][2] * ilocalsize;
10654 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10655 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10656 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10657 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10661 dynamic = model->surfmesh.isanimated;
10662 numsurfacelist = model->nummodelsurfaces;
10663 surfacelist = model->sortedmodelsurfaces;
10664 surfaces = model->data_surfaces;
10667 bih_triangles_count = -1;
10670 if(model->render_bih.numleafs)
10671 bih = &model->render_bih;
10672 else if(model->collision_bih.numleafs)
10673 bih = &model->collision_bih;
10676 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10677 if(bih_triangles_count == 0)
10679 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10681 if(bih_triangles_count > 0)
10683 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10685 surfaceindex = bih_surfaces[triangleindex];
10686 surface = surfaces + surfaceindex;
10687 texture = surface->texture;
10688 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10690 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10692 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10697 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10699 surfaceindex = surfacelist[surfacelistindex];
10700 surface = surfaces + surfaceindex;
10701 // check cull box first because it rejects more than any other check
10702 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10704 // skip transparent surfaces
10705 texture = surface->texture;
10706 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10708 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10710 numtriangles = surface->num_triangles;
10711 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10712 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10717 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10718 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)
10720 int renderentityindex;
10721 float worldmins[3];
10722 float worldmaxs[3];
10723 entity_render_t *ent;
10725 if (!cl_decals_newsystem.integer)
10728 worldmins[0] = worldorigin[0] - worldsize;
10729 worldmins[1] = worldorigin[1] - worldsize;
10730 worldmins[2] = worldorigin[2] - worldsize;
10731 worldmaxs[0] = worldorigin[0] + worldsize;
10732 worldmaxs[1] = worldorigin[1] + worldsize;
10733 worldmaxs[2] = worldorigin[2] + worldsize;
10735 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10737 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10739 ent = r_refdef.scene.entities[renderentityindex];
10740 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10743 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10747 typedef struct r_decalsystem_splatqueue_s
10749 vec3_t worldorigin;
10750 vec3_t worldnormal;
10756 r_decalsystem_splatqueue_t;
10758 int r_decalsystem_numqueued = 0;
10759 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10761 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)
10763 r_decalsystem_splatqueue_t *queue;
10765 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10768 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10769 VectorCopy(worldorigin, queue->worldorigin);
10770 VectorCopy(worldnormal, queue->worldnormal);
10771 Vector4Set(queue->color, r, g, b, a);
10772 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10773 queue->worldsize = worldsize;
10774 queue->decalsequence = cl.decalsequence++;
10777 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10780 r_decalsystem_splatqueue_t *queue;
10782 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10783 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);
10784 r_decalsystem_numqueued = 0;
10787 extern cvar_t cl_decals_max;
10788 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10791 decalsystem_t *decalsystem = &ent->decalsystem;
10798 if (!decalsystem->numdecals)
10801 if (r_showsurfaces.integer)
10804 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10806 R_DecalSystem_Reset(decalsystem);
10810 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10811 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10813 if (decalsystem->lastupdatetime)
10814 frametime = (cl.time - decalsystem->lastupdatetime);
10817 decalsystem->lastupdatetime = cl.time;
10818 decal = decalsystem->decals;
10819 numdecals = decalsystem->numdecals;
10821 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10823 if (decal->color4f[0][3])
10825 decal->lived += frametime;
10826 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10828 memset(decal, 0, sizeof(*decal));
10829 if (decalsystem->freedecal > i)
10830 decalsystem->freedecal = i;
10834 decal = decalsystem->decals;
10835 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10838 // collapse the array by shuffling the tail decals into the gaps
10841 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10842 decalsystem->freedecal++;
10843 if (decalsystem->freedecal == numdecals)
10845 decal[decalsystem->freedecal] = decal[--numdecals];
10848 decalsystem->numdecals = numdecals;
10850 if (numdecals <= 0)
10852 // if there are no decals left, reset decalsystem
10853 R_DecalSystem_Reset(decalsystem);
10857 extern skinframe_t *decalskinframe;
10858 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10861 decalsystem_t *decalsystem = &ent->decalsystem;
10870 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10873 numdecals = decalsystem->numdecals;
10877 if (r_showsurfaces.integer)
10880 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10882 R_DecalSystem_Reset(decalsystem);
10886 // if the model is static it doesn't matter what value we give for
10887 // wantnormals and wanttangents, so this logic uses only rules applicable
10888 // to a model, knowing that they are meaningless otherwise
10889 if (ent == r_refdef.scene.worldentity)
10890 RSurf_ActiveWorldEntity();
10892 RSurf_ActiveModelEntity(ent, false, false, false);
10894 decalsystem->lastupdatetime = cl.time;
10895 decal = decalsystem->decals;
10897 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10899 // update vertex positions for animated models
10900 v3f = decalsystem->vertex3f;
10901 c4f = decalsystem->color4f;
10902 t2f = decalsystem->texcoord2f;
10903 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10905 if (!decal->color4f[0][3])
10908 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10912 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10915 // update color values for fading decals
10916 if (decal->lived >= cl_decals_time.value)
10917 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10921 c4f[ 0] = decal->color4f[0][0] * alpha;
10922 c4f[ 1] = decal->color4f[0][1] * alpha;
10923 c4f[ 2] = decal->color4f[0][2] * alpha;
10925 c4f[ 4] = decal->color4f[1][0] * alpha;
10926 c4f[ 5] = decal->color4f[1][1] * alpha;
10927 c4f[ 6] = decal->color4f[1][2] * alpha;
10929 c4f[ 8] = decal->color4f[2][0] * alpha;
10930 c4f[ 9] = decal->color4f[2][1] * alpha;
10931 c4f[10] = decal->color4f[2][2] * alpha;
10934 t2f[0] = decal->texcoord2f[0][0];
10935 t2f[1] = decal->texcoord2f[0][1];
10936 t2f[2] = decal->texcoord2f[1][0];
10937 t2f[3] = decal->texcoord2f[1][1];
10938 t2f[4] = decal->texcoord2f[2][0];
10939 t2f[5] = decal->texcoord2f[2][1];
10941 // update vertex positions for animated models
10942 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10944 e = rsurface.modelelement3i + 3*decal->triangleindex;
10945 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10946 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10947 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10951 VectorCopy(decal->vertex3f[0], v3f);
10952 VectorCopy(decal->vertex3f[1], v3f + 3);
10953 VectorCopy(decal->vertex3f[2], v3f + 6);
10956 if (r_refdef.fogenabled)
10958 alpha = RSurf_FogVertex(v3f);
10959 VectorScale(c4f, alpha, c4f);
10960 alpha = RSurf_FogVertex(v3f + 3);
10961 VectorScale(c4f + 4, alpha, c4f + 4);
10962 alpha = RSurf_FogVertex(v3f + 6);
10963 VectorScale(c4f + 8, alpha, c4f + 8);
10974 r_refdef.stats.drawndecals += numtris;
10976 // now render the decals all at once
10977 // (this assumes they all use one particle font texture!)
10978 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);
10979 // R_Mesh_ResetTextureState();
10980 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10981 GL_DepthMask(false);
10982 GL_DepthRange(0, 1);
10983 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10984 GL_DepthTest(true);
10985 GL_CullFace(GL_NONE);
10986 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10987 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10988 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10992 static void R_DrawModelDecals(void)
10996 // fade faster when there are too many decals
10997 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10998 for (i = 0;i < r_refdef.scene.numentities;i++)
10999 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11001 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11002 for (i = 0;i < r_refdef.scene.numentities;i++)
11003 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11004 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11006 R_DecalSystem_ApplySplatEntitiesQueue();
11008 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11009 for (i = 0;i < r_refdef.scene.numentities;i++)
11010 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11012 r_refdef.stats.totaldecals += numdecals;
11014 if (r_showsurfaces.integer)
11017 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11019 for (i = 0;i < r_refdef.scene.numentities;i++)
11021 if (!r_refdef.viewcache.entityvisible[i])
11023 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11024 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11028 extern cvar_t mod_collision_bih;
11029 void R_DrawDebugModel(void)
11031 entity_render_t *ent = rsurface.entity;
11032 int i, j, k, l, flagsmask;
11033 const msurface_t *surface;
11034 dp_model_t *model = ent->model;
11037 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11040 if (r_showoverdraw.value > 0)
11042 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11043 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11044 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11045 GL_DepthTest(false);
11046 GL_DepthMask(false);
11047 GL_DepthRange(0, 1);
11048 GL_BlendFunc(GL_ONE, GL_ONE);
11049 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11051 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11053 rsurface.texture = R_GetCurrentTexture(surface->texture);
11054 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11056 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11057 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11058 if (!rsurface.texture->currentlayers->depthmask)
11059 GL_Color(c, 0, 0, 1.0f);
11060 else if (ent == r_refdef.scene.worldentity)
11061 GL_Color(c, c, c, 1.0f);
11063 GL_Color(0, c, 0, 1.0f);
11064 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11068 rsurface.texture = NULL;
11071 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11073 // R_Mesh_ResetTextureState();
11074 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11075 GL_DepthRange(0, 1);
11076 GL_DepthTest(!r_showdisabledepthtest.integer);
11077 GL_DepthMask(false);
11078 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11080 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11084 qboolean cullbox = ent == r_refdef.scene.worldentity;
11085 const q3mbrush_t *brush;
11086 const bih_t *bih = &model->collision_bih;
11087 const bih_leaf_t *bihleaf;
11088 float vertex3f[3][3];
11089 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11091 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11093 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11095 switch (bihleaf->type)
11098 brush = model->brush.data_brushes + bihleaf->itemindex;
11099 if (brush->colbrushf && brush->colbrushf->numtriangles)
11101 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);
11102 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11103 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11106 case BIH_COLLISIONTRIANGLE:
11107 triangleindex = bihleaf->itemindex;
11108 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11109 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11110 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11111 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);
11112 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11113 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11115 case BIH_RENDERTRIANGLE:
11116 triangleindex = bihleaf->itemindex;
11117 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11118 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11119 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11120 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);
11121 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11122 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11128 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11130 if (r_showtris.integer && qglPolygonMode)
11132 if (r_showdisabledepthtest.integer)
11134 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11135 GL_DepthMask(false);
11139 GL_BlendFunc(GL_ONE, GL_ZERO);
11140 GL_DepthMask(true);
11142 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11143 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11145 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11147 rsurface.texture = R_GetCurrentTexture(surface->texture);
11148 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11150 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11151 if (!rsurface.texture->currentlayers->depthmask)
11152 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11153 else if (ent == r_refdef.scene.worldentity)
11154 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11156 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11157 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11161 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11162 rsurface.texture = NULL;
11165 if (r_shownormals.value != 0 && qglBegin)
11167 if (r_showdisabledepthtest.integer)
11169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11170 GL_DepthMask(false);
11174 GL_BlendFunc(GL_ONE, GL_ZERO);
11175 GL_DepthMask(true);
11177 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11179 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11181 rsurface.texture = R_GetCurrentTexture(surface->texture);
11182 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11184 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11185 qglBegin(GL_LINES);
11186 if (r_shownormals.value < 0)
11188 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11190 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11191 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11192 qglVertex3f(v[0], v[1], v[2]);
11193 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11194 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11195 qglVertex3f(v[0], v[1], v[2]);
11198 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11200 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11202 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11203 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11204 qglVertex3f(v[0], v[1], v[2]);
11205 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11206 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11207 qglVertex3f(v[0], v[1], v[2]);
11209 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11211 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11212 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11213 qglVertex3f(v[0], v[1], v[2]);
11214 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11215 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11216 qglVertex3f(v[0], v[1], v[2]);
11218 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11220 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11221 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11222 qglVertex3f(v[0], v[1], v[2]);
11223 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11224 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11225 qglVertex3f(v[0], v[1], v[2]);
11232 rsurface.texture = NULL;
11236 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11237 int r_maxsurfacelist = 0;
11238 const msurface_t **r_surfacelist = NULL;
11239 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11241 int i, j, endj, flagsmask;
11242 dp_model_t *model = r_refdef.scene.worldmodel;
11243 msurface_t *surfaces;
11244 unsigned char *update;
11245 int numsurfacelist = 0;
11249 if (r_maxsurfacelist < model->num_surfaces)
11251 r_maxsurfacelist = model->num_surfaces;
11253 Mem_Free((msurface_t**)r_surfacelist);
11254 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11257 RSurf_ActiveWorldEntity();
11259 surfaces = model->data_surfaces;
11260 update = model->brushq1.lightmapupdateflags;
11262 // update light styles on this submodel
11263 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11265 model_brush_lightstyleinfo_t *style;
11266 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11268 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11270 int *list = style->surfacelist;
11271 style->value = r_refdef.scene.lightstylevalue[style->style];
11272 for (j = 0;j < style->numsurfaces;j++)
11273 update[list[j]] = true;
11278 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11282 R_DrawDebugModel();
11283 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11287 rsurface.lightmaptexture = NULL;
11288 rsurface.deluxemaptexture = NULL;
11289 rsurface.uselightmaptexture = false;
11290 rsurface.texture = NULL;
11291 rsurface.rtlight = NULL;
11292 numsurfacelist = 0;
11293 // add visible surfaces to draw list
11294 for (i = 0;i < model->nummodelsurfaces;i++)
11296 j = model->sortedmodelsurfaces[i];
11297 if (r_refdef.viewcache.world_surfacevisible[j])
11298 r_surfacelist[numsurfacelist++] = surfaces + j;
11300 // update lightmaps if needed
11301 if (model->brushq1.firstrender)
11303 model->brushq1.firstrender = false;
11304 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11306 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11310 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11311 if (r_refdef.viewcache.world_surfacevisible[j])
11313 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11315 // don't do anything if there were no surfaces
11316 if (!numsurfacelist)
11318 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11321 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11323 // add to stats if desired
11324 if (r_speeds.integer && !skysurfaces && !depthonly)
11326 r_refdef.stats.world_surfaces += numsurfacelist;
11327 for (j = 0;j < numsurfacelist;j++)
11328 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11331 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11334 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11336 int i, j, endj, flagsmask;
11337 dp_model_t *model = ent->model;
11338 msurface_t *surfaces;
11339 unsigned char *update;
11340 int numsurfacelist = 0;
11344 if (r_maxsurfacelist < model->num_surfaces)
11346 r_maxsurfacelist = model->num_surfaces;
11348 Mem_Free((msurface_t **)r_surfacelist);
11349 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11352 // if the model is static it doesn't matter what value we give for
11353 // wantnormals and wanttangents, so this logic uses only rules applicable
11354 // to a model, knowing that they are meaningless otherwise
11355 if (ent == r_refdef.scene.worldentity)
11356 RSurf_ActiveWorldEntity();
11357 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11358 RSurf_ActiveModelEntity(ent, false, false, false);
11360 RSurf_ActiveModelEntity(ent, true, true, true);
11361 else if (depthonly)
11363 switch (vid.renderpath)
11365 case RENDERPATH_GL20:
11366 case RENDERPATH_D3D9:
11367 case RENDERPATH_D3D10:
11368 case RENDERPATH_D3D11:
11369 case RENDERPATH_SOFT:
11370 case RENDERPATH_GLES2:
11371 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11373 case RENDERPATH_GL11:
11374 case RENDERPATH_GL13:
11375 case RENDERPATH_GLES1:
11376 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11382 switch (vid.renderpath)
11384 case RENDERPATH_GL20:
11385 case RENDERPATH_D3D9:
11386 case RENDERPATH_D3D10:
11387 case RENDERPATH_D3D11:
11388 case RENDERPATH_SOFT:
11389 case RENDERPATH_GLES2:
11390 RSurf_ActiveModelEntity(ent, true, true, false);
11392 case RENDERPATH_GL11:
11393 case RENDERPATH_GL13:
11394 case RENDERPATH_GLES1:
11395 RSurf_ActiveModelEntity(ent, true, false, false);
11400 surfaces = model->data_surfaces;
11401 update = model->brushq1.lightmapupdateflags;
11403 // update light styles
11404 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11406 model_brush_lightstyleinfo_t *style;
11407 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11409 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11411 int *list = style->surfacelist;
11412 style->value = r_refdef.scene.lightstylevalue[style->style];
11413 for (j = 0;j < style->numsurfaces;j++)
11414 update[list[j]] = true;
11419 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11423 R_DrawDebugModel();
11424 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11428 rsurface.lightmaptexture = NULL;
11429 rsurface.deluxemaptexture = NULL;
11430 rsurface.uselightmaptexture = false;
11431 rsurface.texture = NULL;
11432 rsurface.rtlight = NULL;
11433 numsurfacelist = 0;
11434 // add visible surfaces to draw list
11435 for (i = 0;i < model->nummodelsurfaces;i++)
11436 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11437 // don't do anything if there were no surfaces
11438 if (!numsurfacelist)
11440 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11443 // update lightmaps if needed
11447 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11452 R_BuildLightMap(ent, surfaces + j);
11457 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11459 R_BuildLightMap(ent, surfaces + j);
11460 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11462 // add to stats if desired
11463 if (r_speeds.integer && !skysurfaces && !depthonly)
11465 r_refdef.stats.entities_surfaces += numsurfacelist;
11466 for (j = 0;j < numsurfacelist;j++)
11467 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11470 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11473 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11475 static texture_t texture;
11476 static msurface_t surface;
11477 const msurface_t *surfacelist = &surface;
11479 // fake enough texture and surface state to render this geometry
11481 texture.update_lastrenderframe = -1; // regenerate this texture
11482 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11483 texture.currentskinframe = skinframe;
11484 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11485 texture.offsetmapping = OFFSETMAPPING_OFF;
11486 texture.offsetscale = 1;
11487 texture.specularscalemod = 1;
11488 texture.specularpowermod = 1;
11490 surface.texture = &texture;
11491 surface.num_triangles = numtriangles;
11492 surface.num_firsttriangle = firsttriangle;
11493 surface.num_vertices = numvertices;
11494 surface.num_firstvertex = firstvertex;
11497 rsurface.texture = R_GetCurrentTexture(surface.texture);
11498 rsurface.lightmaptexture = NULL;
11499 rsurface.deluxemaptexture = NULL;
11500 rsurface.uselightmaptexture = false;
11501 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11504 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)
11506 static msurface_t surface;
11507 const msurface_t *surfacelist = &surface;
11509 // fake enough texture and surface state to render this geometry
11510 surface.texture = texture;
11511 surface.num_triangles = numtriangles;
11512 surface.num_firsttriangle = firsttriangle;
11513 surface.num_vertices = numvertices;
11514 surface.num_firstvertex = firstvertex;
11517 rsurface.texture = R_GetCurrentTexture(surface.texture);
11518 rsurface.lightmaptexture = NULL;
11519 rsurface.deluxemaptexture = NULL;
11520 rsurface.uselightmaptexture = false;
11521 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);