X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=04ad617f91290c8c93cd1e66f980eae39cc20b6b;hb=cf74e01c006d2937bf1e3a522efc7b2dd0f40ba2;hp=f60e7e2b5fe4c911d58d4899dfbe50931845a020;hpb=dbd8e60c7e473f960271f3f52d66382e205001db;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index f60e7e2b..04ad617f 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -70,6 +70,10 @@ cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"}; cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"}; cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" }; +cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"}; +cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"}; +cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"}; +cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"}; cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"}; 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)"}; cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"}; @@ -118,6 +122,8 @@ cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rat cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"}; cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"}; 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"}; +cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"}; +cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"}; cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"}; cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"}; @@ -131,21 +137,25 @@ cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the re 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)"}; 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"}; -cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"}; -cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"}; -cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"}; -cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"}; -cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"}; - cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"}; static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"}; static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"}; +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"}; +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"}; +cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"}; +cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"}; +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"}; +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)"}; +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)"}; +cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"}; + 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)"}; cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"}; 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)"}; cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"}; 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)"}; +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)"}; cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"}; cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"}; 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)"}; @@ -163,6 +173,7 @@ cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier" cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"}; cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"}; cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"}; +cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"}; cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"}; cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"}; @@ -195,14 +206,6 @@ cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"}; cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; -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"}; -cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"}; -cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"}; -cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"}; -cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"}; -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)"}; -cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"}; -cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"}; cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"}; cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"}; @@ -222,6 +225,13 @@ static struct r_bloomstate_s int bloomwidth, bloomheight; + textype_t texturetype; + int viewfbo; // used to check if r_viewfbo cvar has changed + + int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working + rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero + rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero + int screentexturewidth, screentextureheight; rtexture_t *texture_screen; /// \note also used for motion blur if enabled! @@ -265,7 +275,7 @@ typedef struct cubemapinfo_s cubemapinfo_t; int r_texture_numcubemaps; -cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS]; +cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS]; unsigned int r_queries[MAX_OCCLUSION_QUERIES]; unsigned int r_numqueries; @@ -660,6 +670,7 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"}, {"#define USEBOUNCEGRID\n", " bouncegrid"}, {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, + {"#define USETRIPPY\n", " trippy"}, }; // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS! @@ -1772,7 +1783,7 @@ void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutatio void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation) { - DPSOFTRAST_SetShader(mode, permutation); + DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer); DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f); DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f); DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time); @@ -1833,8 +1844,9 @@ void R_GLSL_Restart_f(void) memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash)); } break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: break; case RENDERPATH_SOFT: break; @@ -1881,15 +1893,31 @@ void R_GLSL_DumpShader_f(void) Con_Printf("failed to write to hlsl/default.hlsl\n"); } -void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale) +void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy) { + unsigned int permutation = 0; + if (r_trippy.integer && !notrippy) + permutation |= SHADERPERMUTATION_TRIPPY; + permutation |= SHADERPERMUTATION_VIEWTINT; + if (first) + permutation |= SHADERPERMUTATION_DIFFUSE; + if (second) + permutation |= SHADERPERMUTATION_SPECULAR; + if (texturemode == GL_MODULATE) + permutation |= SHADERPERMUTATION_COLORMAPPING; + else if (texturemode == GL_ADD) + permutation |= SHADERPERMUTATION_GLOW; + else if (texturemode == GL_DECAL) + permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; if (!second) texturemode = GL_MODULATE; + if (vid.allowalphatocoverage) + GL_AlphaToCoverage(false); switch (vid.renderpath) { case RENDERPATH_D3D9: #ifdef SUPPORTD3D - 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)))); + R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation); R_Mesh_TexBind(GL20TU_FIRST , first ); R_Mesh_TexBind(GL20TU_SECOND, second); #endif @@ -1902,11 +1930,12 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod break; case RENDERPATH_GL20: case RENDERPATH_GLES2: - 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)))); + R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation); R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first ); R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second); break; case RENDERPATH_GL13: + case RENDERPATH_GLES1: R_Mesh_TexBind(0, first ); R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1); R_Mesh_TexBind(1, second); @@ -1917,20 +1946,25 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod R_Mesh_TexBind(0, first ); break; case RENDERPATH_SOFT: - 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)))); + R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation); R_Mesh_TexBind(GL20TU_FIRST , first ); R_Mesh_TexBind(GL20TU_SECOND, second); break; } } -void R_SetupShader_DepthOrShadow(void) +void R_SetupShader_DepthOrShadow(qboolean notrippy) { + unsigned int permutation = 0; + if (r_trippy.integer && !notrippy) + permutation |= SHADERPERMUTATION_TRIPPY; + if (vid.allowalphatocoverage) + GL_AlphaToCoverage(false); switch (vid.renderpath) { case RENDERPATH_D3D9: #ifdef SUPPORTD3D - R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0); + R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation); #endif break; case RENDERPATH_D3D10: @@ -1941,9 +1975,10 @@ void R_SetupShader_DepthOrShadow(void) break; case RENDERPATH_GL20: case RENDERPATH_GLES2: - R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0); + R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation); break; case RENDERPATH_GL13: + case RENDERPATH_GLES1: R_Mesh_TexBind(0, 0); R_Mesh_TexBind(1, 0); break; @@ -1951,18 +1986,25 @@ void R_SetupShader_DepthOrShadow(void) R_Mesh_TexBind(0, 0); break; case RENDERPATH_SOFT: - R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0); + R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation); break; } } -void R_SetupShader_ShowDepth(void) +void R_SetupShader_ShowDepth(qboolean notrippy) { + int permutation = 0; + if (r_trippy.integer && !notrippy) + permutation |= SHADERPERMUTATION_TRIPPY; + if (r_trippy.integer) + permutation |= SHADERPERMUTATION_TRIPPY; + if (vid.allowalphatocoverage) + GL_AlphaToCoverage(false); switch (vid.renderpath) { case RENDERPATH_D3D9: #ifdef SUPPORTHLSL - R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0); + R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation); #endif break; case RENDERPATH_D3D10: @@ -1973,14 +2015,15 @@ void R_SetupShader_ShowDepth(void) break; case RENDERPATH_GL20: case RENDERPATH_GLES2: - R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0); + R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation); break; case RENDERPATH_GL13: + case RENDERPATH_GLES1: break; case RENDERPATH_GL11: break; case RENDERPATH_SOFT: - R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0); + R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation); break; } } @@ -2056,7 +2099,7 @@ static int R_BlendFuncFlags(int src, int dst) return r; } -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) +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, qboolean notrippy) { // select a permutation of the lighting shader appropriate to this // combination of texture, entity, light source, and fogging, only use the @@ -2070,6 +2113,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float m16f[16]; matrix4x4_t tempmatrix; r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane; + if (r_trippy.integer && !notrippy) + permutation |= SHADERPERMUTATION_TRIPPY; if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) permutation |= SHADERPERMUTATION_ALPHAKILL; if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1]) @@ -2106,52 +2151,46 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, GL_BlendFunc(GL_ONE, GL_ZERO); blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO); } + if (vid.allowalphatocoverage) + GL_AlphaToCoverage(false); } else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY) { if (r_glsl_offsetmapping.integer) { - if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR) - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF) - permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; - else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF) + switch(rsurface.texture->offsetmapping) { - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - if (r_glsl_offsetmapping_reliefmapping.integer) - permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; + case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; + case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_OFF: break; } } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; // normalmap (deferred prepass), may use alpha test on diffuse mode = SHADERMODE_DEFERREDGEOMETRY; - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) - permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; GL_BlendFunc(GL_ONE, GL_ZERO); blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO); + if (vid.allowalphatocoverage) + GL_AlphaToCoverage(false); } else if (rsurfacepass == RSURFPASS_RTLIGHT) { if (r_glsl_offsetmapping.integer) { - if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR) - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF) - permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; - else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF) + switch(rsurface.texture->offsetmapping) { - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - if (r_glsl_offsetmapping_reliefmapping.integer) - permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; + case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; + case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_OFF: break; } } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; // light source mode = SHADERMODE_LIGHTSOURCE; - if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) - permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; if (rsurface.rtlight->currentcubemap != r_texture_whitecube) permutation |= SHADERPERMUTATION_CUBEFILTER; if (diffusescale > 0) @@ -2179,20 +2218,19 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= SHADERPERMUTATION_REFLECTCUBE; GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE); + if (vid.allowalphatocoverage) + GL_AlphaToCoverage(false); } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) { if (r_glsl_offsetmapping.integer) { - if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR) - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF) - permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; - else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF) + switch(rsurface.texture->offsetmapping) { - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - if (r_glsl_offsetmapping_reliefmapping.integer) - permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; + case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; + case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_OFF: break; } } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) @@ -2224,20 +2262,28 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= SHADERPERMUTATION_REFLECTCUBE; GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + // when using alphatocoverage, we don't need alphakill + if (vid.allowalphatocoverage) + { + if (r_transparent_alphatocoverage.integer) + { + GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + permutation &= ~SHADERPERMUTATION_ALPHAKILL; + } + else + GL_AlphaToCoverage(false); + } } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL) { if (r_glsl_offsetmapping.integer) { - if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR) - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF) - permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; - else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF) + switch(rsurface.texture->offsetmapping) { - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - if (r_glsl_offsetmapping_reliefmapping.integer) - permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; + case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; + case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_OFF: break; } } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) @@ -2279,20 +2325,28 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + // when using alphatocoverage, we don't need alphakill + if (vid.allowalphatocoverage) + { + if (r_transparent_alphatocoverage.integer) + { + GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + permutation &= ~SHADERPERMUTATION_ALPHAKILL; + } + else + GL_AlphaToCoverage(false); + } } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) { if (r_glsl_offsetmapping.integer) { - if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR) - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF) - permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; - else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF) + switch(rsurface.texture->offsetmapping) { - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - if (r_glsl_offsetmapping_reliefmapping.integer) - permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; + case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; + case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_OFF: break; } } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) @@ -2331,20 +2385,28 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + // when using alphatocoverage, we don't need alphakill + if (vid.allowalphatocoverage) + { + if (r_transparent_alphatocoverage.integer) + { + GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + permutation &= ~SHADERPERMUTATION_ALPHAKILL; + } + else + GL_AlphaToCoverage(false); + } } else { if (r_glsl_offsetmapping.integer) { - if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR) - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF) - permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; - else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF) + switch(rsurface.texture->offsetmapping) { - permutation |= SHADERPERMUTATION_OFFSETMAPPING; - if (r_glsl_offsetmapping_reliefmapping.integer) - permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING; + case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break; + case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break; + case OFFSETMAPPING_OFF: break; } } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND) @@ -2419,6 +2481,17 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2); + // when using alphatocoverage, we don't need alphakill + if (vid.allowalphatocoverage) + { + if (r_transparent_alphatocoverage.integer) + { + GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0); + permutation &= ~SHADERPERMUTATION_ALPHAKILL; + } + else + GL_AlphaToCoverage(false); + } } if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD)) colormod = dummy_colormod; @@ -2521,7 +2594,12 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist); hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip); hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade); - hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer)); + hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps, + r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, + max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), + 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), + max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer) + ); hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height); @@ -2676,11 +2754,16 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist); if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip); if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade); - if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer)); + if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, + r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, + max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), + 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), + max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer) + ); 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]); if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height); 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);} - if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity); + if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale); if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white ); if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white ); @@ -2728,8 +2811,9 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture); CHECKGLERROR break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: break; case RENDERPATH_SOFT: 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); @@ -2815,7 +2899,12 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist); DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip); DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade); - DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer)); + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, + r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, + max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), + 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), + max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer) + ); DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]); DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height); @@ -2888,7 +2977,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) permutation |= SHADERPERMUTATION_CUBEFILTER; if (diffusescale > 0) permutation |= SHADERPERMUTATION_DIFFUSE; - if (specularscale > 0) + if (specularscale > 0 && r_shadow_gloss.integer > 0) permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE; if (r_shadow_usingshadowmap2d) { @@ -2903,6 +2992,8 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) else if (r_shadow_shadowmappcf) permutation |= SHADERPERMUTATION_SHADOWMAPPCF; } + if (vid.allowalphatocoverage) + GL_AlphaToCoverage(false); Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin); Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld); Matrix4x4_Invert_Simple(&viewtolight, &lighttoview); @@ -2958,8 +3049,9 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture ); if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture ); break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: break; case RENDERPATH_SOFT: R_SetupShader_SetPermutationGLSL(mode, permutation); @@ -3174,7 +3266,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole // check for DDS texture file first if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel))) { - basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel); + basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel); if (basepixels == NULL) return NULL; } @@ -3212,7 +3304,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { basepixels_width = image_width; basepixels_height = image_height; - skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL); + skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL); if (textureflags & TEXF_ALPHA) { for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4) @@ -3234,16 +3326,16 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole pixels[j+2] = 255; pixels[j+3] = basepixels[j+3]; } - skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL); + 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); Mem_Free(pixels); } } R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]); //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]); if (r_savedds && qglGetCompressedTexImageARB && skinframe->base) - R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha); + R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha); if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog) - R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true); + R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); } if (r_loaddds) @@ -3265,7 +3357,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole mymiplevel = savemiplevel; if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL) { - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + 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); Mem_Free(pixels); pixels = NULL; } @@ -3273,7 +3365,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4); Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value); - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + 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); Mem_Free(pixels); Mem_Free(bumppixels); } @@ -3281,60 +3373,60 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4); Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value); - skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + 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); Mem_Free(pixels); } if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap) - R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true); + R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); } // _luma is supported only for tenebrae compatibility // _glow is the preferred name mymiplevel = savemiplevel; - if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))) + 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)))) { - skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow) - R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true); + R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); Mem_Free(pixels);pixels = NULL; } mymiplevel = savemiplevel; - if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))) + if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel))) { - skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss) - R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true); + R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); Mem_Free(pixels); pixels = NULL; } mymiplevel = savemiplevel; - if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))) + if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel))) { - skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants) - R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false); + R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false); Mem_Free(pixels); pixels = NULL; } mymiplevel = savemiplevel; - if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))) + if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel))) { - skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt) - R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false); + R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false); Mem_Free(pixels); pixels = NULL; } mymiplevel = savemiplevel; - if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))) + if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel))) { - skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect) - R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true); + R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); Mem_Free(pixels); pixels = NULL; } @@ -3346,7 +3438,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole } // this is only used by .spr32 sprites, HL .spr files, HL .bsp files -skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height) +skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB) { int i; unsigned char *temp1, *temp2; @@ -3387,7 +3479,7 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co 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); Mem_Free(temp1); } - skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL); + skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL); if (textureflags & TEXF_ALPHA) { for (i = 3;i < width * height * 4;i += 4) @@ -3514,20 +3606,20 @@ static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboo if (skinframe->qgenerateglow) { skinframe->qgenerateglow = false; - skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow + skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow } if (colormapped) { skinframe->qgeneratebase = false; - 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); - skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite); - skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite); + skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap); + skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite); + skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite); } else { skinframe->qgeneratemerged = false; - 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); + skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete); } if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase) @@ -3674,7 +3766,7 @@ rtexture_t *R_LoadCubemap(const char *basename) // generate an image name based on the base and and suffix dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix); // load it - if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL))) + if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL))) { // an image loaded, make sure width and height are equal if (image_width == image_height && (!cubemappixels || image_width == cubemapsize)) @@ -3703,7 +3795,7 @@ rtexture_t *R_LoadCubemap(const char *basename) if (developer_loading.integer) Con_Printf("loading cubemap \"%s\"\n", basename); - cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); Mem_Free(cubemappixels); } else @@ -3725,14 +3817,36 @@ rtexture_t *R_GetCubemap(const char *basename) { int i; for (i = 0;i < r_texture_numcubemaps;i++) - if (!strcasecmp(r_texture_cubemaps[i].basename, basename)) - return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube; - if (i >= MAX_CUBEMAPS) + if (r_texture_cubemaps[i] != NULL) + if (!strcasecmp(r_texture_cubemaps[i]->basename, basename)) + return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube; + if (i >= MAX_CUBEMAPS || !r_main_mempool) return r_texture_whitecube; r_texture_numcubemaps++; - strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename)); - r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename); - return r_texture_cubemaps[i].texture; + r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t)); + strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename)); + r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename); + return r_texture_cubemaps[i]->texture; +} + +void R_FreeCubemap(const char *basename) +{ + int i; + + for (i = 0;i < r_texture_numcubemaps;i++) + { + if (r_texture_cubemaps[i] != NULL) + { + if (r_texture_cubemaps[i]->texture) + { + if (developer_loading.integer) + Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename); + R_FreeTexture(r_texture_cubemaps[i]->texture); + Mem_Free(r_texture_cubemaps[i]); + r_texture_cubemaps[i] = NULL; + } + } + } } void R_FreeCubemaps(void) @@ -3741,9 +3855,13 @@ void R_FreeCubemaps(void) for (i = 0;i < r_texture_numcubemaps;i++) { if (developer_loading.integer) - Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename); - if (r_texture_cubemaps[i].texture) - R_FreeTexture(r_texture_cubemaps[i].texture); + Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename); + if (r_texture_cubemaps[i] != NULL) + { + if (r_texture_cubemaps[i]->texture) + R_FreeTexture(r_texture_cubemaps[i]->texture); + Mem_Free(r_texture_cubemaps[i]); + } } r_texture_numcubemaps = 0; } @@ -3824,6 +3942,7 @@ void gl_main_start(void) case RENDERPATH_D3D10: case RENDERPATH_D3D11: case RENDERPATH_SOFT: + case RENDERPATH_GLES2: Cvar_SetValueQuick(&r_textureunits, vid.texunits); Cvar_SetValueQuick(&gl_combine, 1); Cvar_SetValueQuick(&r_glsl, 1); @@ -3832,6 +3951,7 @@ void gl_main_start(void) r_loadfog = false; break; case RENDERPATH_GL13: + case RENDERPATH_GLES1: Cvar_SetValueQuick(&r_textureunits, vid.texunits); Cvar_SetValueQuick(&gl_combine, 1); Cvar_SetValueQuick(&r_glsl, 0); @@ -3847,14 +3967,6 @@ void gl_main_start(void) r_loadgloss = false; r_loadfog = true; break; - case RENDERPATH_GLES2: - Cvar_SetValueQuick(&r_textureunits, 1); - Cvar_SetValueQuick(&gl_combine, 1); - Cvar_SetValueQuick(&r_glsl, 1); - r_loadnormalmap = true; - r_loadgloss = false; - r_loadfog = false; - break; } R_AnimCache_Free(); @@ -3901,6 +4013,9 @@ void gl_main_start(void) hlslshaderstring = NULL; memset(&r_svbsp, 0, sizeof (r_svbsp)); + memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps)); + r_texture_numcubemaps = 0; + r_refdef.fogmasktable_density = 0; } @@ -3916,6 +4031,7 @@ void gl_main_shutdown(void) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: + case RENDERPATH_GLES1: case RENDERPATH_GLES2: if (r_maxqueries) qglDeleteQueriesARB(r_maxqueries, r_queries); @@ -4037,6 +4153,10 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_farclip_base); Cvar_RegisterVariable(&r_farclip_world); Cvar_RegisterVariable(&r_nearclip); + Cvar_RegisterVariable(&r_deformvertexes); + Cvar_RegisterVariable(&r_transparent); + Cvar_RegisterVariable(&r_transparent_alphatocoverage); + Cvar_RegisterVariable(&r_showoverdraw); Cvar_RegisterVariable(&r_showbboxes); Cvar_RegisterVariable(&r_showsurfaces); Cvar_RegisterVariable(&r_showtris); @@ -4082,21 +4202,27 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_fog_clear); Cvar_RegisterVariable(&r_drawfog); Cvar_RegisterVariable(&r_transparentdepthmasking); + Cvar_RegisterVariable(&r_transparent_sortmaxdist); + Cvar_RegisterVariable(&r_transparent_sortarraysize); Cvar_RegisterVariable(&r_texture_dds_load); Cvar_RegisterVariable(&r_texture_dds_save); - Cvar_RegisterVariable(&r_texture_convertsRGB_2d); - Cvar_RegisterVariable(&r_texture_convertsRGB_skin); - Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap); - Cvar_RegisterVariable(&r_texture_convertsRGB_skybox); - Cvar_RegisterVariable(&r_texture_convertsRGB_particles); Cvar_RegisterVariable(&r_textureunits); Cvar_RegisterVariable(&gl_combine); + Cvar_RegisterVariable(&r_viewfbo); + Cvar_RegisterVariable(&r_viewscale); + Cvar_RegisterVariable(&r_viewscale_fpsscaling); + Cvar_RegisterVariable(&r_viewscale_fpsscaling_min); + Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply); + Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize); + Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax); + Cvar_RegisterVariable(&r_viewscale_fpsscaling_target); Cvar_RegisterVariable(&r_glsl); Cvar_RegisterVariable(&r_glsl_deluxemapping); Cvar_RegisterVariable(&r_glsl_offsetmapping); Cvar_RegisterVariable(&r_glsl_offsetmapping_steps); Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping); Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps); + Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps); Cvar_RegisterVariable(&r_glsl_offsetmapping_scale); Cvar_RegisterVariable(&r_glsl_postprocess); Cvar_RegisterVariable(&r_glsl_postprocess_uservec1); @@ -4114,6 +4240,8 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_water_refractdistort); Cvar_RegisterVariable(&r_water_reflectdistort); Cvar_RegisterVariable(&r_water_scissormode); + Cvar_RegisterVariable(&r_water_lowquality); + Cvar_RegisterVariable(&r_lerpsprites); Cvar_RegisterVariable(&r_lerpmodels); Cvar_RegisterVariable(&r_lerplightstyles); @@ -4146,15 +4274,6 @@ void GL_Main_Init(void) if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE) Cvar_SetValue("r_fullbrights", 0); R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL); - - Cvar_RegisterVariable(&r_track_sprites); - Cvar_RegisterVariable(&r_track_sprites_flags); - Cvar_RegisterVariable(&r_track_sprites_scalew); - Cvar_RegisterVariable(&r_track_sprites_scaleh); - Cvar_RegisterVariable(&r_overheadsprites_perspective); - Cvar_RegisterVariable(&r_overheadsprites_pushback); - Cvar_RegisterVariable(&r_overheadsprites_scalex); - Cvar_RegisterVariable(&r_overheadsprites_scaley); } extern void R_Textures_Init(void); @@ -4225,6 +4344,8 @@ int R_CullBox(const vec3_t mins, const vec3_t maxs) { int i; mplane_t *p; + if (r_trippy.integer) + return false; for (i = 0;i < r_refdef.view.numfrustumplanes;i++) { // skip nearclip plane, it often culls portals when you are very close, and is almost never useful @@ -4275,6 +4396,8 @@ int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, c { int i; const mplane_t *p; + if (r_trippy.integer) + return false; for (i = 0;i < numplanes;i++) { p = planes + i; @@ -4520,7 +4643,7 @@ qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qbool else { // see if this ent is worth caching - if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton)) + if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices) return false; // get some memory for this entity and generate mesh data numvertices = model->surfmesh.num_vertices; @@ -4552,8 +4675,9 @@ void R_AnimCache_CacheVisibleEntities(void) case RENDERPATH_D3D11: case RENDERPATH_GLES2: break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: wanttangents = false; break; case RENDERPATH_SOFT: @@ -4573,6 +4697,8 @@ void R_AnimCache_CacheVisibleEntities(void) //================================================================================== +extern cvar_t r_overheadsprites_pushback; + static void R_View_UpdateEntityLighting (void) { int i; @@ -4603,7 +4729,7 @@ static void R_View_UpdateEntityLighting (void) VectorClear(ent->modellight_ambient); VectorClear(ent->modellight_diffuse); VectorClear(tempdiffusenormal); - if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint) + if (ent->flags & RENDER_LIGHT) { vec3_t org; Matrix4x4_OriginFromMatrix(&ent->matrix, org); @@ -4614,7 +4740,7 @@ static void R_View_UpdateEntityLighting (void) { if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites org[2] = org[2] + r_overheadsprites_pushback.value; - R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); + R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); } else R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP); @@ -4745,24 +4871,6 @@ static void R_View_UpdateEntityVisible (void) 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)) r_refdef.viewcache.entityvisible[i] = true; } - if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane) - // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling - { - for (i = 0;i < r_refdef.scene.numentities;i++) - { - ent = r_refdef.scene.entities[i]; - if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*'))) - { - samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer; - if (samples < 0) - continue; // temp entities do pvs only - if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs)) - ent->last_trace_visibility = realtime; - if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value) - r_refdef.viewcache.entityvisible[i] = 0; - } - } - } } else { @@ -4773,6 +4881,26 @@ static void R_View_UpdateEntityVisible (void) 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)); } } + if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer) + // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling + { + for (i = 0;i < r_refdef.scene.numentities;i++) + { + if (!r_refdef.viewcache.entityvisible[i]) + continue; + ent = r_refdef.scene.entities[i]; + if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*'))) + { + samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer; + if (samples < 0) + continue; // temp entities do pvs only + if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs)) + ent->last_trace_visibility = realtime; + if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value) + r_refdef.viewcache.entityvisible[i] = 0; + } + } + } } /// only used if skyrendermasked, and normally returns false @@ -4807,6 +4935,17 @@ static void R_DrawModels(void) continue; ent = r_refdef.scene.entities[i]; r_refdef.stats.entities++; + /* + if (ent->model && !strncmp(ent->model->name, "models/proto_", 13)) + { + vec3_t f, l, u, o; + Matrix4x4_ToVectors(&ent->matrix, f, l, u, o); + Con_Printf("R_DrawModels\n"); + 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]); + 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); + 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); + } + */ if (ent->model && ent->model->Draw != NULL) ent->model->Draw(ent); else @@ -4906,14 +5045,15 @@ static void R_View_SetFrustum(const int *scissor) case RENDERPATH_D3D9: case RENDERPATH_D3D10: case RENDERPATH_D3D11: - case RENDERPATH_SOFT: // non-flipped y coordinates fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height); fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height); break; + case RENDERPATH_SOFT: case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: + case RENDERPATH_GLES1: case RENDERPATH_GLES2: // non-flipped y coordinates fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height); @@ -5108,10 +5248,29 @@ void R_View_Update(void) R_View_UpdateEntityLighting(); } +float viewscalefpsadjusted = 1.0f; + +void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight) +{ + float scale = r_viewscale.value * sqrt(viewscalefpsadjusted); + scale = bound(0.03125f, scale, 1.0f); + *outwidth = (int)ceil(width * scale); + *outheight = (int)ceil(height * scale); +} + +void R_Mesh_SetMainRenderTargets(void) +{ + if (r_bloomstate.fbo_framebuffer) + R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL); + else + R_Mesh_ResetRenderTargets(); +} + void R_SetupView(qboolean allowwaterclippingplane) { const float *customclipplane = NULL; float plane[4]; + int scaledwidth, scaledheight; if (r_refdef.view.useclipplane && allowwaterclippingplane) { // LordHavoc: couldn't figure out how to make this approach the @@ -5122,17 +5281,29 @@ void R_SetupView(qboolean allowwaterclippingplane) plane[0] = r_refdef.view.clipplane.normal[0]; plane[1] = r_refdef.view.clipplane.normal[1]; plane[2] = r_refdef.view.clipplane.normal[2]; - plane[3] = dist; - customclipplane = plane; + plane[3] = -dist; + if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane; } + R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight); if (!r_refdef.view.useperspective) - R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane); + 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); else if (vid.stencil && r_useinfinitefarclip.integer) - R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane); + 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); else - R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane); + 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); + R_Mesh_SetMainRenderTargets(); R_SetViewport(&r_refdef.view.viewport); + if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT) + { + matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix; + float screenplane[4]; + Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix); + Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix); + Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix); + Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane); + DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]); + } } void R_EntityMatrix(const matrix4x4_t *matrix) @@ -5160,8 +5331,9 @@ void R_EntityMatrix(const matrix4x4_t *matrix) case RENDERPATH_D3D11: Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__); break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: qglLoadMatrixf(gl_modelview16f);CHECKGLERROR break; case RENDERPATH_SOFT: @@ -5184,6 +5356,7 @@ void R_ResetViewRendering2D(void) // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom 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); + R_Mesh_ResetRenderTargets(); R_SetViewport(&viewport); GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); GL_Color(1, 1, 1, 1); @@ -5203,6 +5376,7 @@ void R_ResetViewRendering2D(void) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: + case RENDERPATH_GLES1: case RENDERPATH_GLES2: qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR break; @@ -5238,6 +5412,7 @@ void R_ResetViewRendering3D(void) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: + case RENDERPATH_GLES1: case RENDERPATH_GLES2: qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR break; @@ -5287,15 +5462,15 @@ static void R_Water_StartFrame(void) case RENDERPATH_SOFT: case RENDERPATH_GLES2: break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: return; } // set waterwidth and waterheight to the water resolution that will be // used (often less than the screen resolution for faster rendering) - waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width); - waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height); + R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight); // calculate desired texture sizes // can't use water if the card does not support the texture size @@ -5341,17 +5516,20 @@ static void R_Water_StartFrame(void) if (r_waterstate.texturewidth) { + int scaledwidth, scaledheight; + r_waterstate.enabled = true; // when doing a reduced render (HDR) we want to use a smaller area r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width); r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height); + R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight); // set up variables that will be used in shader setup - r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth; - r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight; - r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth; - r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight; + r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth; + r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight; + r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth; + r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight; } r_waterstate.maxwaterplanes = MAX_WATERPLANES; @@ -5442,17 +5620,44 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno) } } +extern cvar_t r_drawparticles; +extern cvar_t r_drawdecals; + static void R_Water_ProcessPlanes(void) { int myscissor[4]; r_refdef_view_t originalview; r_refdef_view_t myview; - int planeindex; + int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0; r_waterstate_waterplane_t *p; vec3_t visorigin; originalview = r_refdef.view; + // lowquality hack, temporarily shut down some cvars and restore afterwards + qualityreduction = r_water_lowquality.integer; + if (qualityreduction > 0) + { + if (qualityreduction >= 1) + { + old_r_shadows = r_shadows.integer; + old_r_worldrtlight = r_shadow_realtime_world.integer; + old_r_dlight = r_shadow_realtime_dlight.integer; + Cvar_SetValueQuick(&r_shadows, 0); + Cvar_SetValueQuick(&r_shadow_realtime_world, 0); + Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0); + } + if (qualityreduction >= 2) + { + old_r_dynamic = r_dynamic.integer; + old_r_particles = r_drawparticles.integer; + old_r_decals = r_drawdecals.integer; + Cvar_SetValueQuick(&r_dynamic, 0); + Cvar_SetValueQuick(&r_drawparticles, 0); + Cvar_SetValueQuick(&r_drawdecals, 0); + } + } + // make sure enough textures are allocated for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) { @@ -5505,7 +5710,6 @@ static void R_Water_ProcessPlanes(void) // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems) Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin); r_refdef.view.clipplane = p->plane; - // reverse the cullface settings for this render r_refdef.view.cullface_front = GL_FRONT; r_refdef.view.cullface_back = GL_BACK; @@ -5626,23 +5830,61 @@ static void R_Water_ProcessPlanes(void) } } + if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1); r_waterstate.renderingscene = false; r_refdef.view = originalview; R_ResetViewRendering3D(); R_ClearScreen(r_refdef.fogenabled); R_View_Update(); - return; + goto finish; error: r_refdef.view = originalview; r_waterstate.renderingscene = false; Cvar_SetValueQuick(&r_water, 0); Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n"); - return; +finish: + // lowquality hack, restore cvars + if (qualityreduction > 0) + { + if (qualityreduction >= 1) + { + Cvar_SetValueQuick(&r_shadows, old_r_shadows); + Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight); + Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight); + } + if (qualityreduction >= 2) + { + Cvar_SetValueQuick(&r_dynamic, old_r_dynamic); + Cvar_SetValueQuick(&r_drawparticles, old_r_particles); + Cvar_SetValueQuick(&r_drawdecals, old_r_decals); + } + } } void R_Bloom_StartFrame(void) { int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight; + int viewwidth, viewheight; + textype_t textype; + + if (r_viewscale_fpsscaling.integer) + { + double actualframetime; + double targetframetime; + double adjust; + actualframetime = r_refdef.lastdrawscreentime; + targetframetime = (1.0 / r_viewscale_fpsscaling_target.value); + adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value; + adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value); + if (r_viewscale_fpsscaling_stepsize.value > 0) + adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value; + viewscalefpsadjusted += adjust; + viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f); + } + else + viewscalefpsadjusted = 1.0f; + + R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight); switch(vid.renderpath) { @@ -5653,8 +5895,9 @@ void R_Bloom_StartFrame(void) case RENDERPATH_SOFT: case RENDERPATH_GLES2: break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: return; } @@ -5669,8 +5912,8 @@ void R_Bloom_StartFrame(void) // calculate desired texture sizes if (vid.support.arb_texture_non_power_of_two) { - screentexturewidth = r_refdef.view.width; - screentextureheight = r_refdef.view.height; + screentexturewidth = vid.width; + screentextureheight = vid.height; bloomtexturewidth = r_bloomstate.bloomwidth; bloomtextureheight = r_bloomstate.bloomheight; } @@ -5690,31 +5933,83 @@ void R_Bloom_StartFrame(void) Cvar_SetValueQuick(&r_damageblur, 0); } - 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))) + 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) screentexturewidth = screentextureheight = 0; if (!r_hdr.integer && !r_bloom.integer) bloomtexturewidth = bloomtextureheight = 0; + textype = TEXTYPE_COLORBUFFER; + switch (vid.renderpath) + { + case RENDERPATH_GL20: + case RENDERPATH_GLES2: + if (vid.support.ext_framebuffer_object) + { + if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F; + if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F; + } + break; + case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: + case RENDERPATH_D3D9: + case RENDERPATH_D3D10: + case RENDERPATH_D3D11: + case RENDERPATH_SOFT: + break; + } + // allocate textures as needed - if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight) + if (r_bloomstate.screentexturewidth != screentexturewidth + || r_bloomstate.screentextureheight != screentextureheight + || r_bloomstate.bloomtexturewidth != bloomtexturewidth + || r_bloomstate.bloomtextureheight != bloomtextureheight + || r_bloomstate.texturetype != textype + || r_bloomstate.viewfbo != r_viewfbo.integer) { + if (r_bloomstate.texture_bloom) + R_FreeTexture(r_bloomstate.texture_bloom); + r_bloomstate.texture_bloom = NULL; if (r_bloomstate.texture_screen) R_FreeTexture(r_bloomstate.texture_screen); r_bloomstate.texture_screen = NULL; + if (r_bloomstate.fbo_framebuffer) + R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer); + r_bloomstate.fbo_framebuffer = 0; + if (r_bloomstate.texture_framebuffercolor) + R_FreeTexture(r_bloomstate.texture_framebuffercolor); + r_bloomstate.texture_framebuffercolor = NULL; + if (r_bloomstate.texture_framebufferdepth) + R_FreeTexture(r_bloomstate.texture_framebufferdepth); + r_bloomstate.texture_framebufferdepth = NULL; r_bloomstate.screentexturewidth = screentexturewidth; r_bloomstate.screentextureheight = screentextureheight; if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight) - r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL); - } - if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight) - { - if (r_bloomstate.texture_bloom) - R_FreeTexture(r_bloomstate.texture_bloom); - r_bloomstate.texture_bloom = NULL; + 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); + if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object) + { + // FIXME: choose depth bits based on a cvar + r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false); + 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); + r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL); + R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL); + // render depth into one texture and normalmap into the other + if (qglDrawBuffer) + { + int status; + qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR + qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR + status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) + Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status); + } + } r_bloomstate.bloomtexturewidth = bloomtexturewidth; r_bloomstate.bloomtextureheight = bloomtextureheight; if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight) - r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + 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); + r_bloomstate.viewfbo = r_viewfbo.integer; + r_bloomstate.texturetype = textype; } // when doing a reduced render (HDR) we want to use a smaller area @@ -5727,10 +6022,10 @@ void R_Bloom_StartFrame(void) // set up a texcoord array for the full resolution screen image // (we have to keep this around to copy back during final render) r_bloomstate.screentexcoord2f[0] = 0; - r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; - r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; - r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight; - r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth; + r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight; + r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth; + r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight; + r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth; r_bloomstate.screentexcoord2f[5] = 0; r_bloomstate.screentexcoord2f[6] = 0; r_bloomstate.screentexcoord2f[7] = 0; @@ -5752,6 +6047,7 @@ void R_Bloom_StartFrame(void) case RENDERPATH_GL13: case RENDERPATH_GL20: case RENDERPATH_SOFT: + case RENDERPATH_GLES1: case RENDERPATH_GLES2: break; case RENDERPATH_D3D9: @@ -5770,13 +6066,16 @@ void R_Bloom_StartFrame(void) break; } - if (r_hdr.integer || r_bloom.integer) + if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth) { r_bloomstate.enabled = true; - r_bloomstate.hdr = r_hdr.integer != 0; + r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer; } 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); + + if (r_bloomstate.fbo_framebuffer) + r_refdef.view.clear = true; } void R_Bloom_CopyBloomTexture(float colorscale) @@ -5785,6 +6084,7 @@ void R_Bloom_CopyBloomTexture(float colorscale) // scale down screen texture to the bloom texture size CHECKGLERROR + R_Mesh_SetMainRenderTargets(); R_SetViewport(&r_bloomstate.viewport); GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(colorscale, colorscale, colorscale, 1); @@ -5794,8 +6094,9 @@ void R_Bloom_CopyBloomTexture(float colorscale) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: - case RENDERPATH_SOFT: + case RENDERPATH_GLES1: case RENDERPATH_GLES2: + case RENDERPATH_SOFT: R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f); break; case RENDERPATH_D3D9: @@ -5805,7 +6106,7 @@ void R_Bloom_CopyBloomTexture(float colorscale) break; } // TODO: do boxfilter scale-down in shader? - R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; @@ -5841,7 +6142,7 @@ void R_Bloom_MakeTexture(void) GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); GL_Color(r,r,r,1); R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f); - R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; @@ -5852,12 +6153,12 @@ void R_Bloom_MakeTexture(void) range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320; brighten = r_bloom_brighten.value; - if (r_hdr.integer) + if (r_bloomstate.hdr) brighten *= r_hdr_range.value; brighten = sqrt(brighten); if(range >= 1) brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle" - R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true); for (dir = 0;dir < 2;dir++) { @@ -5987,6 +6288,7 @@ static void R_BlendView(void) if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); } R_ResetViewRendering2D(); + R_Mesh_SetMainRenderTargets(); if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0)) { @@ -6026,8 +6328,9 @@ static void R_BlendView(void) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: - case RENDERPATH_SOFT: + case RENDERPATH_GLES1: case RENDERPATH_GLES2: + case RENDERPATH_SOFT: R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f); break; case RENDERPATH_D3D9: @@ -6036,7 +6339,7 @@ static void R_BlendView(void) R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f); break; } - R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; } @@ -6055,7 +6358,7 @@ static void R_BlendView(void) R_ResetViewRendering2D(); GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); } @@ -6152,17 +6455,18 @@ static void R_BlendView(void) break; } R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); - r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height; break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: if (r_refdef.viewblend[3] >= (1.0f / 256.0f)) { // apply a color tint to the whole view R_ResetViewRendering2D(); GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); } @@ -6337,8 +6641,9 @@ void R_UpdateVariables(void) // remove GLSL gamma texture } break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: break; } } @@ -6381,6 +6686,8 @@ R_RenderView ================ */ int dpsoftrast_test; +extern void R_Shadow_UpdateBounceGridTexture(void); +extern cvar_t r_shadow_bouncegrid; void R_RenderView(void) { matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix; @@ -6457,7 +6764,7 @@ void R_RenderView(void) r_refdef.view.clear = true; // this produces a bloom texture to be used in R_BlendView() later - if (r_hdr.integer && r_bloomstate.bloomwidth) + if (r_bloomstate.hdr) { R_HDR_RenderBloomTexture(); // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures @@ -6470,6 +6777,10 @@ void R_RenderView(void) if (r_timereport_active) R_TimeReport("visibility"); + R_Shadow_UpdateBounceGridTexture(); + if (r_timereport_active && r_shadow_bouncegrid.integer) + R_TimeReport("bouncegrid"); + r_waterstate.numwaterplanes = 0; if (r_waterstate.enabled) R_RenderWaterPlanes(); @@ -6716,11 +7027,14 @@ void R_RenderScene(void) } } - R_MeshQueue_RenderTransparent(); - if (r_timereport_active) - R_TimeReport("drawtrans"); + if (r_transparent.integer) + { + R_MeshQueue_RenderTransparent(); + if (r_timereport_active) + R_TimeReport("drawtrans"); + } - 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)) + 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)) { r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity); if (r_timereport_active) @@ -6810,7 +7124,7 @@ void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, floa } R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL); R_Mesh_ResetTextureState(); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0); } @@ -6826,14 +7140,14 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh return; GL_CullFace(GL_NONE); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); prog = 0; SV_VM_Begin(); for (i = 0;i < numsurfaces;i++) { edict = PRVM_EDICT_NUM(surfacelist[i]); - switch ((int)edict->fields.server->solid) + switch ((int)PRVM_serveredictfloat(edict, solid)) { case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break; case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break; @@ -6871,9 +7185,9 @@ static void R_DrawEntityBBoxes(void) if (edict->priv.server->free) continue; // exclude the following for now, as they don't live in world coordinate space and can't be solid: - if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0) + if(PRVM_serveredictedict(edict, tag_entity) != 0) continue; - if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0) + if(PRVM_serveredictedict(edict, viewmodelforclient) != 0) continue; VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center); R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL); @@ -6976,7 +7290,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight } } // R_Mesh_ResetTextureState(); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL); R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0); } @@ -7164,7 +7478,7 @@ static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms) static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) { double index, f; - index = parms[2] + r_refdef.scene.time * parms[3]; + index = parms[2] + rsurface.shadertime * parms[3]; index -= floor(index); switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1)) { @@ -7182,7 +7496,9 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) index *= 4; f = index - floor(index); if (index < 1) - f = f; + { + // f = f; + } else if (index < 2) f = 1 - f; else if (index < 3) @@ -7200,7 +7516,8 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags) { int w, h, idx; - float f; + double f; + double offsetd[2]; float tcmat[12]; matrix4x4_t matrix, temp; switch(tcmod->tcmod) @@ -7219,19 +7536,22 @@ void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *t break; case Q3TCMOD_ROTATE: Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0); - Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1); + Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1); Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0); break; case Q3TCMOD_SCALE: Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1); break; case Q3TCMOD_SCROLL: - Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0); + // extra care is needed because of precision breakdown with large values of time + offsetd[0] = tcmod->parms[0] * rsurface.shadertime; + offsetd[1] = tcmod->parms[1] * rsurface.shadertime; + Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0); break; case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures) w = (int) tcmod->parms[0]; h = (int) tcmod->parms[1]; - f = r_refdef.scene.time / (tcmod->parms[2] * w * h); + f = rsurface.shadertime / (tcmod->parms[2] * w * h); f = f - floor(f); idx = (int) floor(f * w * h); Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0); @@ -7258,7 +7578,7 @@ void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *t void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname) { - int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS; + int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP; char name[MAX_QPATH]; skinframe_t *skinframe; unsigned char pixels[296*194]; @@ -7309,7 +7629,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) if (model->skinscenes) { if (model->skinscenes[s].framecount > 1) - s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount; + s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount; else s = model->skinscenes[s].firstframe; } @@ -7320,9 +7640,9 @@ texture_t *R_GetCurrentTexture(texture_t *t) // use an alternate animation if the entity's frame is not 0, // and only if the texture has an alternate animation if (rsurface.ent_alttextures && t->anim_total[1]) - t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0]; + t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0]; else - t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0]; + t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0]; } texture->currentframe = t; } @@ -7342,16 +7662,16 @@ texture_t *R_GetCurrentTexture(texture_t *t) R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin); t->currentskinframe = r_qwskincache[i].skinframe; if (t->currentskinframe == NULL) - t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes]; + t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)]; } else if (t->numskinframes >= 2) - t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes]; + t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)]; if (t->backgroundnumskinframes >= 2) - t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes]; + t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)]; t->currentmaterialflags = t->basematerialflags; t->currentalpha = rsurface.colormod[3]; - if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer)) + if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer)) t->currentalpha *= r_wateralpha.value; if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later @@ -7361,7 +7681,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; else if (FAKELIGHT_ENABLED) { - // no modellight if using fakelight for the map + // no modellight if using fakelight for the map } else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) { @@ -7388,6 +7708,11 @@ texture_t *R_GetCurrentTexture(texture_t *t) } else t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA); + if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA))) + { + // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on + t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST; + } if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED)) t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH; @@ -7592,8 +7917,8 @@ void RSurf_ActiveWorldEntity(void) memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param)); rsurface.ent_skinnum = 0; rsurface.ent_qwskin = -1; - rsurface.ent_shadertime = 0; rsurface.ent_flags = r_refdef.scene.worldentity->flags; + rsurface.shadertime = r_refdef.scene.time; rsurface.matrix = identitymatrix; rsurface.inversematrix = identitymatrix; rsurface.matrixscale = 1; @@ -7703,8 +8028,8 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param)); rsurface.ent_skinnum = ent->skinnum; 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; - rsurface.ent_shadertime = ent->shadertime; rsurface.ent_flags = ent->flags; + rsurface.shadertime = r_refdef.scene.time - ent->shadertime; rsurface.matrix = ent->matrix; rsurface.inversematrix = ent->inversematrix; rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix); @@ -7733,7 +8058,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value; rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value; } - if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0)) + if (model->surfmesh.isanimated && model->AnimateVertices) { if (ent->animcache_vertex3f) { @@ -7872,8 +8197,8 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve rsurface.skeleton = NULL; rsurface.ent_skinnum = 0; rsurface.ent_qwskin = -1; - rsurface.ent_shadertime = shadertime; rsurface.ent_flags = entflags; + rsurface.shadertime = r_refdef.scene.time - shadertime; rsurface.modelnumvertices = numvertices; rsurface.modelnumtriangles = numtriangles; rsurface.matrix = *matrix; @@ -8119,7 +8444,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR; } - for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++) + for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++) { switch (deform->deform) { @@ -8385,20 +8710,53 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP)) { if (batchneed & BATCHNEED_ARRAY_VERTEX) - memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3])); - if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f) - memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3])); - if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f) { - memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3])); - memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3])); + if (rsurface.batchvertex3f) + memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3])); + else + memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3])); + } + if (batchneed & BATCHNEED_ARRAY_NORMAL) + { + if (rsurface.modelnormal3f) + memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3])); + else + memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3])); + } + if (batchneed & BATCHNEED_ARRAY_VECTOR) + { + if (rsurface.modelsvector3f) + { + memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3])); + memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3])); + } + else + { + memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3])); + memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3])); + } + } + if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) + { + if (rsurface.modellightmapcolor4f) + memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4])); + else + memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4])); + } + if (batchneed & BATCHNEED_ARRAY_TEXCOORD) + { + if (rsurface.modeltexcoordtexture2f) + memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2])); + else + memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2])); + } + if (batchneed & BATCHNEED_ARRAY_LIGHTMAP) + { + if (rsurface.modeltexcoordlightmap2f) + memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2])); + else + memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2])); } - if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f) - memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4])); - if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f) - memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2])); - if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f) - memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2])); } RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex); numvertices += surfacenumvertices; @@ -8487,7 +8845,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const // if vertices are deformed (sprite flares and things in maps, possibly // water waves, bulges and other deformations), modify the copied vertices // in place - for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++) + for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++) { switch (deform->deform) { @@ -8522,6 +8880,11 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f); // rsurface.batchnormal3f_vertexbuffer = NULL; // rsurface.batchnormal3f_bufferoffset = 0; + // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1) + if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex)) + Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0); + if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex)) + 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); // a single autosprite surface can contain multiple sprites... for (j = 0;j < batchnumvertices - 3;j += 4) { @@ -8658,9 +9021,9 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const float vertex[3]; float *normal = rsurface.batchnormal3f + 3*j; VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex); - normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]); - 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]); - 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]); + normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]); + normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]); + normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]); VectorNormalize(normal); } if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL @@ -8724,7 +9087,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const // rsurface.batchnormal3f_bufferoffset = 0; for (j = 0;j < batchnumvertices;j++) { - scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1]; + scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1]; VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j); } // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check @@ -8818,7 +9181,7 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT) { amplitude = rsurface.texture->tcmods[0].parms[1]; - animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3]; + animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3]; // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2])); // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL; // rsurface.batchtexcoordtexture2f_bufferoffset = 0; @@ -9206,6 +9569,12 @@ static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a float f; const float *v; float *c; + + // fake shading + rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4])); + rsurface.passcolor4f_vertexbuffer = 0; + rsurface.passcolor4f_bufferoffset = 0; + for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4) { f = 1 - RSurf_FogVertex(v); @@ -9232,7 +9601,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_ // transparent sky would be ridiculous if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) return; - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); skyrenderlater = true; RSurf_SetupDepthAndCulling(); GL_DepthMask(true); @@ -9242,12 +9611,12 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_ // in Quake3 maps as it causes problems with q3map2 sky tricks, // and skymasking also looks very bad when noclipping outside the // level, so don't use it then either. - if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis) + if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer) { R_Mesh_ResetTextureState(); if (skyrendermasked) { - R_SetupShader_DepthOrShadow(); + R_SetupShader_DepthOrShadow(false); // depth-only (masking) GL_ColorMask(0,0,0,0); // just to make sure that braindead drivers don't draw @@ -9261,7 +9630,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_ } else { - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); // fog sky GL_BlendFunc(GL_ONE, GL_ZERO); RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); @@ -9286,9 +9655,8 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface { // render screenspace normalmap to texture GL_DepthMask(true); - R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false); RSurf_DrawBatch(); - return; } // bind lightmap texture @@ -9314,18 +9682,18 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface { // render water or distortion background GL_DepthMask(true); - 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)); + 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), false); RSurf_DrawBatch(); // blend surface on top GL_DepthMask(false); - R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false); RSurf_DrawBatch(); } else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)) { // render surface with reflection texture as input GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); - 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)); + 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), false); RSurf_DrawBatch(); } } @@ -9334,7 +9702,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface // render surface batch normally GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)); - R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0); RSurf_DrawBatch(); } @@ -9557,7 +9925,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const float c[4]; // R_Mesh_ResetTextureState(); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); if(rsurface.texture && rsurface.texture->currentskinframe) { @@ -9663,7 +10031,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const RSurf_DrawBatch_GL11_ClampColor(); R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); RSurf_DrawBatch(); } else if (!r_refdef.view.showdebug) @@ -9755,6 +10123,7 @@ static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass); break; case RENDERPATH_GL13: + case RENDERPATH_GLES1: R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth); break; case RENDERPATH_GL11: @@ -9784,6 +10153,7 @@ static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass); break; case RENDERPATH_GL13: + case RENDERPATH_GLES1: R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth); break; case RENDERPATH_GL11: @@ -9799,8 +10169,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const int texturenumsurfaces, endsurface; texture_t *texture; const msurface_t *surface; -#define MAXBATCH_TRANSPARENTSURFACES 256 - const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES]; + const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE]; // if the model is static it doesn't matter what value we give for // wantnormals and wanttangents, so this logic uses only rules applicable @@ -9821,8 +10190,9 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const case RENDERPATH_GLES2: RSurf_ActiveModelEntity(ent, true, true, false); break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: RSurf_ActiveModelEntity(ent, true, false, false); break; } @@ -9863,7 +10233,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); // R_Mesh_ResetTextureState(); - R_SetupShader_DepthOrShadow(); + R_SetupShader_DepthOrShadow(false); } RSurf_SetupDepthAndCulling(); RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist); @@ -9884,7 +10254,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const texture = surface->texture; rsurface.texture = R_GetCurrentTexture(texture); // scan ahead until we find a different texture - endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces); + endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces); texturenumsurfaces = 0; texturesurfacelist[texturenumsurfaces++] = surface; if(FAKELIGHT_ENABLED) @@ -9975,7 +10345,7 @@ static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurf else R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass); } - else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer) + else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3)) R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); else if (!rsurface.texture->currentnumlayers) return; @@ -10053,7 +10423,7 @@ static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurf else R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass); } - else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer) + else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3)) R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist); else if (!rsurface.texture->currentnumlayers) return; @@ -10176,7 +10546,7 @@ void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, in vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i]; R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0); } @@ -10271,6 +10641,9 @@ static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float decal->texcoord2f[1][1] = t1[1]; decal->texcoord2f[2][0] = t2[0]; decal->texcoord2f[2][1] = t2[1]; + TriangleNormal(v0, v1, v2, decal->plane); + VectorNormalize(decal->plane); + decal->plane[3] = DotProduct(v0, decal->plane); } extern cvar_t cl_decals_bias; @@ -10627,10 +11000,10 @@ static void R_DrawModelDecals_FadeEntity(entity_render_t *ent) lifetime = cl_decals_time.value + cl_decals_fadetime.value; if (decalsystem->lastupdatetime) - frametime = (cl.time - decalsystem->lastupdatetime); + frametime = (r_refdef.scene.time - decalsystem->lastupdatetime); else frametime = 0; - decalsystem->lastupdatetime = cl.time; + decalsystem->lastupdatetime = r_refdef.scene.time; decal = decalsystem->decals; numdecals = decalsystem->numdecals; @@ -10707,7 +11080,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) else RSurf_ActiveModelEntity(ent, false, false, false); - decalsystem->lastupdatetime = cl.time; + decalsystem->lastupdatetime = r_refdef.scene.time; decal = decalsystem->decals; faderate = 1.0f / max(0.001f, cl_decals_fadetime.value); @@ -10724,6 +11097,10 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) if (surfacevisible && !surfacevisible[decal->surfaceindex]) continue; + // skip backfaces + if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3]) + continue; + // update color values for fading decals if (decal->lived >= cl_decals_time.value) alpha = 1 - faderate * (decal->lived - cl_decals_time.value); @@ -10787,7 +11164,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) // now render the decals all at once // (this assumes they all use one particle font texture!) - 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); + RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false); // R_Mesh_ResetTextureState(); R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f); GL_DepthMask(false); @@ -10796,7 +11173,7 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) GL_DepthTest(true); GL_CullFace(GL_NONE); GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false); R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0); } } @@ -10846,33 +11223,44 @@ void R_DrawDebugModel(void) dp_model_t *model = ent->model; vec3_t v; - switch(vid.renderpath) - { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - break; - case RENDERPATH_D3D9: - //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - return; - case RENDERPATH_D3D10: - Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - return; - case RENDERPATH_D3D11: - Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - return; - case RENDERPATH_SOFT: - //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - return; - case RENDERPATH_GLES2: - //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); + if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity) return; + + if (r_showoverdraw.value > 0) + { + float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f; + flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL; + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); + GL_DepthTest(false); + GL_DepthMask(false); + GL_DepthRange(0, 1); + GL_BlendFunc(GL_ONE, GL_ONE); + for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + { + if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) + continue; + rsurface.texture = R_GetCurrentTexture(surface->texture); + if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) + { + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface); + GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back); + if (!rsurface.texture->currentlayers->depthmask) + GL_Color(c, 0, 0, 1.0f); + else if (ent == r_refdef.scene.worldentity) + GL_Color(c, c, c, 1.0f); + else + GL_Color(0, c, 0, 1.0f); + R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL); + RSurf_DrawBatch(); + } + } + rsurface.texture = NULL; } flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL; // R_Mesh_ResetTextureState(); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false); GL_DepthRange(0, 1); GL_DepthTest(!r_showdisabledepthtest.integer); GL_DepthMask(false); @@ -10928,7 +11316,7 @@ void R_DrawDebugModel(void) GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset); - if (r_showtris.integer || (r_shownormals.value != 0)) + if (r_showtris.integer && qglPolygonMode) { if (r_showdisabledepthtest.integer) { @@ -10940,6 +11328,7 @@ void R_DrawDebugModel(void) GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); } + qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) { if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) @@ -10948,23 +11337,43 @@ void R_DrawDebugModel(void) if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) { RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface); - if (r_showtris.value > 0) - { - if (!rsurface.texture->currentlayers->depthmask) - GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value); - else if (ent == r_refdef.scene.worldentity) - GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value); - else - GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value); - R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL); - qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - RSurf_DrawBatch(); - qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - CHECKGLERROR - } - if (r_shownormals.value < 0) + if (!rsurface.texture->currentlayers->depthmask) + GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value); + else if (ent == r_refdef.scene.worldentity) + GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value); + else + GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value); + R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL); + RSurf_DrawBatch(); + } + } + qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR + rsurface.texture = NULL; + } + + if (r_shownormals.value != 0 && qglBegin) + { + if (r_showdisabledepthtest.integer) + { + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + } + else + { + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + } + for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + { + if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) + continue; + rsurface.texture = R_GetCurrentTexture(surface->texture); + if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) + { + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface); + qglBegin(GL_LINES); + if (r_shownormals.value < 0 && rsurface.batchnormal3f) { - qglBegin(GL_LINES); for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++) { VectorCopy(rsurface.batchvertex3f + l * 3, v); @@ -10974,12 +11383,9 @@ void R_DrawDebugModel(void) GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1); qglVertex3f(v[0], v[1], v[2]); } - qglEnd(); - CHECKGLERROR } if (r_shownormals.value > 0 && rsurface.batchsvector3f) { - qglBegin(GL_LINES); for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++) { VectorCopy(rsurface.batchvertex3f + l * 3, v); @@ -10989,9 +11395,9 @@ void R_DrawDebugModel(void) GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1); qglVertex3f(v[0], v[1], v[2]); } - qglEnd(); - CHECKGLERROR - qglBegin(GL_LINES); + } + if (r_shownormals.value > 0 && rsurface.batchtvector3f) + { for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++) { VectorCopy(rsurface.batchvertex3f + l * 3, v); @@ -11001,9 +11407,9 @@ void R_DrawDebugModel(void) GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1); qglVertex3f(v[0], v[1], v[2]); } - qglEnd(); - CHECKGLERROR - qglBegin(GL_LINES); + } + if (r_shownormals.value > 0 && rsurface.batchnormal3f) + { for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++) { VectorCopy(rsurface.batchvertex3f + l * 3, v); @@ -11013,9 +11419,9 @@ void R_DrawDebugModel(void) GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1); qglVertex3f(v[0], v[1], v[2]); } - qglEnd(); - CHECKGLERROR } + qglEnd(); + CHECKGLERROR } } rsurface.texture = NULL; @@ -11159,8 +11565,9 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr case RENDERPATH_GLES2: RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false); break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: RSurf_ActiveModelEntity(ent, model->wantnormals, false, false); break; } @@ -11177,8 +11584,9 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr case RENDERPATH_GLES2: RSurf_ActiveModelEntity(ent, true, true, false); break; - case RENDERPATH_GL13: case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: RSurf_ActiveModelEntity(ent, true, false, false); break; }