X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=d907ef3eb84befb9b2f723a182685ab0b41280cc;hb=cfee52a1ec9db338098789cae89ae5cf1f7a6fbf;hp=435cefe566289a665eefe3492695b77b1bf378ca;hpb=4e82f39f2505c30be145c98de8bb8aa166c6858c;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index 435cefe5..d907ef3e 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -99,6 +99,7 @@ cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", " cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"}; cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"}; cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"}; +cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"}; cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"}; cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"}; @@ -126,6 +127,7 @@ 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_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"}; 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"}; @@ -161,6 +163,8 @@ cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_re 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_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"}; +cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."}; 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)"}; cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"}; @@ -178,6 +182,8 @@ cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "h 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_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"}; +cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"}; 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"}; @@ -186,16 +192,15 @@ cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll aro cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"}; cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"}; + cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"}; cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"}; cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"}; cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"}; cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"}; -cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"}; cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"}; cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"}; -cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"}; cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"}; cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"}; cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"}; @@ -203,6 +208,7 @@ cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalu cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"}; cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"}; cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"}; +cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"}; cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"}; @@ -224,36 +230,7 @@ extern cvar_t v_glslgamma_2d; extern qboolean v_flipped_state; -static struct r_bloomstate_s -{ - qboolean enabled; - qboolean hdr; - - 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! - - int bloomtexturewidth, bloomtextureheight; - rtexture_t *texture_bloom; - - // arrays for rendering the screen passes - float screentexcoord2f[8]; - float bloomtexcoord2f[8]; - float offsettexcoord2f[8]; - - r_viewport_t viewport; -} -r_bloomstate; - -r_waterstate_t r_waterstate; +r_framebufferstate_t r_fb; /// shadow volume bsp struct with automatically growing nodes buffer svbsp_t r_svbsp; @@ -371,7 +348,7 @@ static void R_BuildBlankTextures(void) data[2] = 128; // normal X data[1] = 128; // normal Y data[0] = 255; // normal Z - data[3] = 128; // height + data[3] = 255; // height r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL); data[0] = 255; data[1] = 255; @@ -713,8 +690,8 @@ shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] = {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"}, - {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"}, - {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"}, + {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"}, + {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"}, {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"}, @@ -823,6 +800,8 @@ typedef struct r_glsl_permutation_s int loc_LightDir; int loc_LightPosition; int loc_OffsetMapping_ScaleSteps; + int loc_OffsetMapping_LodDistance; + int loc_OffsetMapping_Bias; int loc_PixelSize; int loc_ReflectColor; int loc_ReflectFactor; @@ -869,16 +848,17 @@ enum SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled - SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending + SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending + SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping }; -#define SHADERSTATICPARMS_COUNT 7 +#define SHADERSTATICPARMS_COUNT 8 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT]; static int shaderstaticparms_count = 0; static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0}; #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F)) -qboolean R_CompileShader_CheckStaticParms(void) +static qboolean R_CompileShader_CheckStaticParms(void) { static int r_compileshader_staticparms_save[1]; memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms)); @@ -902,6 +882,8 @@ qboolean R_CompileShader_CheckStaticParms(void) if (r_glsl_postprocess_uservec4_enable.integer) R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4); } + if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD); return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0; } @@ -910,7 +892,7 @@ qboolean R_CompileShader_CheckStaticParms(void) shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \ else \ shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n" -void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation) +static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation) { shaderstaticparms_count = 0; @@ -922,6 +904,7 @@ void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation) R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3"); R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4"); R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD"); } /// information about each possible shader permutation @@ -1140,6 +1123,8 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir"); p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition"); p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps"); + p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance"); + p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias"); p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize"); p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor"); p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor"); @@ -1247,7 +1232,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode Mem_Free(fragmentstring); } -void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation) +static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation) { r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation); if (r_glsl_permutation != perm) @@ -1379,7 +1364,9 @@ typedef enum D3DPSREGISTER_e D3DPSREGISTER_ViewToLight = 44, // float4x4 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4 D3DPSREGISTER_NormalmapScrollBlend = 52, - // next at 53 + D3DPSREGISTER_OffsetMapping_LodDistance = 53, + D3DPSREGISTER_OffsetMapping_Bias = 54, + // next at 54 } D3DPSREGISTER_t; @@ -1471,8 +1458,8 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";} if (!debugshader) { - vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize); - psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize); + vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize); + psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize); } if ((!vsbin && vertstring) || (!psbin && fragstring)) { @@ -1523,9 +1510,9 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c if (debugshader) { // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog); -// FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize()); - FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring)); - vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable); +// FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize()); + FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring)); + vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable); } else vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable); @@ -1539,7 +1526,7 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c if (vslog) { strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize())); - Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp); + Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp); vslog->Release(); } } @@ -1548,9 +1535,9 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c if (debugshader) { // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog); -// FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize()); - FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring)); - psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable); +// FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize()); + FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring)); + psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable); } else psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable); @@ -1564,23 +1551,23 @@ static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, c if (pslog) { strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize())); - Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp); + Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp); pslog->Release(); } } Sys_UnloadLibrary(&d3dx9_dll); } else - Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n"); + Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n"); } if (vsbin && psbin) { vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader); if (FAILED(vsresult)) - Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult); + Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult); psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader); if (FAILED(psresult)) - Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult); + Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult); } // free the shader data vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0); @@ -1791,7 +1778,7 @@ void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutatio } #endif -void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation) +static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation) { DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer); DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f); @@ -1799,7 +1786,7 @@ void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutatio DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time); } -void R_GLSL_Restart_f(void) +static void R_GLSL_Restart_f(void) { unsigned int i, limit; if (glslshaderstring && glslshaderstring != builtinshaderstring) @@ -1863,7 +1850,7 @@ void R_GLSL_Restart_f(void) } } -void R_GLSL_DumpShader_f(void) +static void R_GLSL_DumpShader_f(void) { int i; qfile_t *file; @@ -1903,7 +1890,7 @@ 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, qboolean usegamma, qboolean notrippy) +void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha) { unsigned int permutation = 0; if (r_trippy.integer && !notrippy) @@ -1915,12 +1902,14 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod permutation |= SHADERPERMUTATION_SPECULAR; if (texturemode == GL_MODULATE) permutation |= SHADERPERMUTATION_COLORMAPPING; - if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial) - permutation |= SHADERPERMUTATION_GAMMARAMPS; else if (texturemode == GL_ADD) permutation |= SHADERPERMUTATION_GLOW; else if (texturemode == GL_DECAL) permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND; + if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial) + permutation |= SHADERPERMUTATION_GAMMARAMPS; + if (suppresstexalpha) + permutation |= SHADERPERMUTATION_REFLECTCUBE; if (!second) texturemode = GL_MODULATE; if (vid.allowalphatocoverage) @@ -1969,6 +1958,11 @@ void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemod } } +void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy) +{ + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false); +} + void R_SetupShader_DepthOrShadow(qboolean notrippy) { unsigned int permutation = 0; @@ -2170,7 +2164,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY) { - if (r_glsl_offsetmapping.integer) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { switch(rsurface.texture->offsetmapping) { @@ -2191,7 +2185,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else if (rsurfacepass == RSURFPASS_RTLIGHT) { - if (r_glsl_offsetmapping.integer) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { switch(rsurface.texture->offsetmapping) { @@ -2237,7 +2231,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) { - if (r_glsl_offsetmapping.integer) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { switch(rsurface.texture->offsetmapping) { @@ -2290,7 +2284,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL) { - if (r_glsl_offsetmapping.integer) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { switch(rsurface.texture->offsetmapping) { @@ -2353,7 +2347,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) { - if (r_glsl_offsetmapping.integer) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { switch(rsurface.texture->offsetmapping) { @@ -2413,7 +2407,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } else { - if (r_glsl_offsetmapping.integer) + if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f)) { switch(rsurface.texture->offsetmapping) { @@ -2552,7 +2546,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // additive passes are only darkened by fog, not tinted hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0); - hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); } else { @@ -2584,20 +2578,20 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, else hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]); hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); - hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]); - hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]); + hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]); + hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]); hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]); hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]); hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin); hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin); - hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); if (mode == SHADERMODE_WATER) hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); } hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); - hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); + hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); if (rsurface.texture->pantstexture) hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]); @@ -2617,6 +2611,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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) ); + hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer); + hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias); 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); @@ -2700,7 +2696,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // additive passes are only darkened by fog, not tinted if (r_glsl_permutation->loc_FogColor >= 0) qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); } else { @@ -2735,13 +2731,13 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]); } if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); - if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]); - if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]); + if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]); + if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]); if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]); if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]); if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin); if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); } if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);} @@ -2751,7 +2747,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); - if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); + if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); if (r_glsl_permutation->loc_Color_Pants >= 0) { @@ -2777,6 +2773,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer); + if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias); 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);} @@ -2848,7 +2846,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // additive passes are only darkened by fog, not tinted DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); } else { @@ -2880,13 +2878,13 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, else DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); - DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]); - DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]); + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]); + DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]); DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin); DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]); } {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);} @@ -2896,7 +2894,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); - DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1)); DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); if (DPSOFTRAST_UNIFORM_Color_Pants >= 0) { @@ -2922,6 +2920,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer); + DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias); 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); @@ -3027,7 +3027,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range); hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); - hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); 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); @@ -3055,7 +3055,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range); if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); - if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); 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); @@ -3079,7 +3079,7 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range); DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); - DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f)); + DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f); 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); @@ -3182,7 +3182,7 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1); for (item = r_skinframe.hash[hashindex];item;item = item->next) - if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc) + if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc))) break; if (!item) { @@ -3195,13 +3195,35 @@ skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewid memset(item, 0, sizeof(*item)); strlcpy(item->basename, basename, sizeof(item->basename)); item->base = dyntexture; // either NULL or dyntexture handle - item->textureflags = textureflags; + item->textureflags = textureflags & ~TEXF_FORCE_RELOAD; item->comparewidth = comparewidth; item->compareheight = compareheight; item->comparecrc = comparecrc; item->next = r_skinframe.hash[hashindex]; r_skinframe.hash[hashindex] = item; } + else if (textureflags & TEXF_FORCE_RELOAD) + { + rtexture_t *dyntexture; + // check whether its a dynamic texture + dyntexture = CL_GetDynTexture( basename ); + if (!add && !dyntexture) + return NULL; + if (item->merged == item->base) + item->merged = NULL; + // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black] + R_PurgeTexture(item->stain );item->stain = NULL; + R_PurgeTexture(item->merged);item->merged = NULL; + R_PurgeTexture(item->base );item->base = NULL; + R_PurgeTexture(item->pants );item->pants = NULL; + R_PurgeTexture(item->shirt );item->shirt = NULL; + R_PurgeTexture(item->nmap );item->nmap = NULL; + R_PurgeTexture(item->gloss );item->gloss = NULL; + R_PurgeTexture(item->glow );item->glow = NULL; + R_PurgeTexture(item->fog );item->fog = NULL; + R_PurgeTexture(item->reflect);item->reflect = NULL; + item->loadsequence = 0; + } else if( item->base == NULL ) { rtexture_t *dyntexture; @@ -3267,6 +3289,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole int miplevel = R_PicmipForFlags(textureflags); int savemiplevel = miplevel; int mymiplevel; + char vabuf[1024]; if (cls.state == ca_dedicated) return NULL; @@ -3281,7 +3304,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole Image_StripImageExtension(name, basename, sizeof(basename)); // check for DDS texture file first - if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel))) + if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel))) { basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel); if (basepixels == NULL) @@ -3296,6 +3319,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole // we've got some pixels to store, so really allocate this new texture now if (!skinframe) skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true); + textureflags &= ~TEXF_FORCE_RELOAD; skinframe->stain = NULL; skinframe->merged = NULL; skinframe->base = NULL; @@ -3314,7 +3338,7 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole skinframe->hasalpha = ddshasalpha; VectorCopy(ddsavgcolor, skinframe->avgcolor); if (r_loadfog && skinframe->hasalpha) - skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel); + skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel); //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]); } else @@ -3343,7 +3367,7 @@ 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL); + skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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); } } @@ -3351,9 +3375,9 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole #ifndef USE_GLES2 //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), r_texture_dds_save.integer < 2, skinframe->hasalpha); + R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "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), r_texture_dds_save.integer < 2, true); + R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); #endif } @@ -3361,30 +3385,30 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { mymiplevel = savemiplevel; if (r_loadnormalmap) - skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel); - skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); + skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel); + skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); if (r_loadgloss) - skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); - skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); - skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); - skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel); + skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); + skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); + skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); + skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel); } // _norm is the name used by tenebrae and has been adopted as standard if (r_loadnormalmap && skinframe->nmap == NULL) { mymiplevel = savemiplevel; - if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL) + if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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; } - else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL) + else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL) { 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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); } @@ -3392,71 +3416,71 @@ 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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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); } #ifndef USE_GLES2 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap) - R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); + R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); #endif } // _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, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel)))) + if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%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, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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); #ifndef USE_GLES2 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow) - R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); + R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); #endif Mem_Free(pixels);pixels = NULL; } mymiplevel = savemiplevel; - if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel))) + if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%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, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); #ifndef USE_GLES2 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss) - R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); + R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); #endif Mem_Free(pixels); pixels = NULL; } mymiplevel = savemiplevel; - if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel))) + if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%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, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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); #ifndef USE_GLES2 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants) - R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false); + R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false); #endif Mem_Free(pixels); pixels = NULL; } mymiplevel = savemiplevel; - if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel))) + if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%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, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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); #ifndef USE_GLES2 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt) - R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false); + R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false); #endif Mem_Free(pixels); pixels = NULL; } mymiplevel = savemiplevel; - if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel))) + if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%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, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL); + skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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); #ifndef USE_GLES2 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect) - R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); + R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true); #endif Mem_Free(pixels); pixels = NULL; @@ -3474,14 +3498,16 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co int i; unsigned char *temp1, *temp2; skinframe_t *skinframe; + char vabuf[1024]; if (cls.state == ca_dedicated) return NULL; // if already loaded just return it, otherwise make a new skinframe - skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true); + skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true); if (skinframe && skinframe->base) return skinframe; + textureflags &= ~TEXF_FORCE_RELOAD; skinframe->stain = NULL; skinframe->merged = NULL; @@ -3507,7 +3533,7 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8); temp2 = temp1 + width * height * 4; Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); - 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); + skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%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, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL); @@ -3527,7 +3553,7 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co memcpy(fogpixels, skindata, width * height * 4); for (i = 0;i < width * height * 4;i += 4) fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255; - skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL); + skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL); Mem_Free(fogpixels); } } @@ -3551,6 +3577,7 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true); if (skinframe && skinframe->base) return skinframe; + textureflags &= ~TEXF_FORCE_RELOAD; skinframe->stain = NULL; skinframe->merged = NULL; @@ -3599,6 +3626,7 @@ static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboo int width; int height; unsigned char *skindata; + char vabuf[1024]; if (!skinframe->qpixels) return; @@ -3630,22 +3658,22 @@ static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboo // use either a custom palette or the quake palette Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete); Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); - skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL); + skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL); Mem_Free(temp1); } if (skinframe->qgenerateglow) { skinframe->qgenerateglow = false; - 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 + skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%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, 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); + skinframe->base = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%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(vabuf, sizeof(vabuf), "%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(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite); } else { @@ -3664,6 +3692,7 @@ skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, co { int i; skinframe_t *skinframe; + char vabuf[1024]; if (cls.state == ca_dedicated) return NULL; @@ -3672,6 +3701,7 @@ skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, co skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true); if (skinframe && skinframe->base) return skinframe; + textureflags &= ~TEXF_FORCE_RELOAD; skinframe->stain = NULL; skinframe->merged = NULL; @@ -3704,7 +3734,7 @@ skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, co } } if (r_loadfog && skinframe->hasalpha) - skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette); + skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette); } R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]); @@ -3778,7 +3808,7 @@ static suffixinfo_t suffix[3][6] = static int componentorder[4] = {0, 1, 2, 3}; -rtexture_t *R_LoadCubemap(const char *basename) +static rtexture_t *R_LoadCubemap(const char *basename) { int i, j, cubemapsize; unsigned char *cubemappixels, *image_buffer; @@ -3860,44 +3890,7 @@ rtexture_t *R_GetCubemap(const char *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) -{ - int i; - 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] != NULL) - { - if (r_texture_cubemaps[i]->texture) - R_FreeTexture(r_texture_cubemaps[i]->texture); - Mem_Free(r_texture_cubemaps[i]); - } - } - r_texture_numcubemaps = 0; -} - -void R_Main_FreeViewCache(void) +static void R_Main_FreeViewCache(void) { if (r_refdef.viewcache.entityvisible) Mem_Free(r_refdef.viewcache.entityvisible); @@ -3910,7 +3903,7 @@ void R_Main_FreeViewCache(void) memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache)); } -void R_Main_ResizeViewCache(void) +static void R_Main_ResizeViewCache(void) { int numentities = r_refdef.scene.numentities; int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1; @@ -3949,7 +3942,7 @@ void R_Main_ResizeViewCache(void) } extern rtexture_t *loadingscreentexture; -void gl_main_start(void) +static void gl_main_start(void) { loadingscreentexture = NULL; r_texture_blanknormalmap = NULL; @@ -4030,8 +4023,7 @@ void gl_main_start(void) r_texture_fogheighttexture = NULL; r_texture_gammaramps = NULL; //r_texture_fogintensity = NULL; - memset(&r_bloomstate, 0, sizeof(r_bloomstate)); - memset(&r_waterstate, 0, sizeof(r_waterstate)); + memset(&r_fb, 0, sizeof(r_fb)); r_glsl_permutation = NULL; memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash)); Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256); @@ -4050,7 +4042,7 @@ void gl_main_start(void) r_refdef.fogmasktable_density = 0; } -void gl_main_shutdown(void) +static void gl_main_shutdown(void) { R_AnimCache_Free(); R_FrameData_Reset(); @@ -4109,8 +4101,7 @@ void gl_main_shutdown(void) r_texture_gammaramps = NULL; r_texture_numcubemaps = 0; //r_texture_fogintensity = NULL; - memset(&r_bloomstate, 0, sizeof(r_bloomstate)); - memset(&r_waterstate, 0, sizeof(r_waterstate)); + memset(&r_fb, 0, sizeof(r_fb)); R_GLSL_Restart_f(); r_glsl_permutation = NULL; @@ -4125,8 +4116,7 @@ void gl_main_shutdown(void) hlslshaderstring = NULL; } -extern void CL_ParseEntityLump(char *entitystring); -void gl_main_newmap(void) +static void gl_main_newmap(void) { // FIXME: move this code to client char *entities, entname[MAX_QPATH]; @@ -4213,6 +4203,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples); Cvar_RegisterVariable(&r_cullentities_trace_enlarge); Cvar_RegisterVariable(&r_cullentities_trace_delay); + Cvar_RegisterVariable(&r_sortentities); Cvar_RegisterVariable(&r_drawviewmodel); Cvar_RegisterVariable(&r_drawexteriormodel); Cvar_RegisterVariable(&r_speeds); @@ -4239,6 +4230,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_fog_clear); Cvar_RegisterVariable(&r_drawfog); Cvar_RegisterVariable(&r_transparentdepthmasking); + Cvar_RegisterVariable(&r_transparent_sortmindist); Cvar_RegisterVariable(&r_transparent_sortmaxdist); Cvar_RegisterVariable(&r_transparent_sortarraysize); Cvar_RegisterVariable(&r_texture_dds_load); @@ -4261,6 +4253,8 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps); Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps); Cvar_RegisterVariable(&r_glsl_offsetmapping_scale); + Cvar_RegisterVariable(&r_glsl_offsetmapping_lod); + Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance); Cvar_RegisterVariable(&r_glsl_postprocess); Cvar_RegisterVariable(&r_glsl_postprocess_uservec1); Cvar_RegisterVariable(&r_glsl_postprocess_uservec2); @@ -4278,6 +4272,8 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_water_reflectdistort); Cvar_RegisterVariable(&r_water_scissormode); Cvar_RegisterVariable(&r_water_lowquality); + Cvar_RegisterVariable(&r_water_hideplayer); + Cvar_RegisterVariable(&r_water_fbo); Cvar_RegisterVariable(&r_lerpsprites); Cvar_RegisterVariable(&r_lerpmodels); @@ -4290,10 +4286,8 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_bloom_resolution); Cvar_RegisterVariable(&r_bloom_colorexponent); Cvar_RegisterVariable(&r_bloom_colorsubtract); - Cvar_RegisterVariable(&r_hdr); Cvar_RegisterVariable(&r_hdr_scenebrightness); Cvar_RegisterVariable(&r_hdr_glowintensity); - Cvar_RegisterVariable(&r_hdr_range); Cvar_RegisterVariable(&r_hdr_irisadaptation); Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier); Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue); @@ -4301,6 +4295,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_hdr_irisadaptation_value); Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up); Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down); + Cvar_RegisterVariable(&r_hdr_irisadaptation_radius); Cvar_RegisterVariable(&r_smoothnormals_areaweighting); Cvar_RegisterVariable(&developer_texturelogging); Cvar_RegisterVariable(&gl_lightmaps); @@ -4314,20 +4309,6 @@ void GL_Main_Init(void) R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL); } -extern void R_Textures_Init(void); -extern void GL_Draw_Init(void); -extern void GL_Main_Init(void); -extern void R_Shadow_Init(void); -extern void R_Sky_Init(void); -extern void GL_Surf_Init(void); -extern void R_Particles_Init(void); -extern void R_Explosion_Init(void); -extern void gl_backend_init(void); -extern void Sbar_Init(void); -extern void R_LightningBeams_Init(void); -extern void Mod_RenderInit(void); -extern void Font_Init(void); - void Render_Init(void) { gl_backend_init(); @@ -4508,7 +4489,7 @@ void R_FrameData_Reset(void) } } -void R_FrameData_Resize(void) +static void R_FrameData_Resize(void) { size_t wantedsize; wantedsize = (size_t)(r_framedatasize.value * 1024*1024); @@ -4622,7 +4603,7 @@ void R_AnimCache_ClearCache(void) } } -void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices) +static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices) { int i; @@ -4751,8 +4732,8 @@ static void R_View_UpdateEntityLighting (void) { ent = r_refdef.scene.entities[i]; - // skip unseen models - if (!r_refdef.viewcache.entityvisible[i] && skipunseen) + // skip unseen models and models that updated by CSQC + if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT) continue; // skip bsp models @@ -4892,8 +4873,8 @@ static void R_View_UpdateEntityVisible (void) entity_render_t *ent; renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) - : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) - : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL + : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) + : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL; if (!r_drawviewmodel.integer) renderimask |= RENDER_VIEWMODEL; @@ -4908,7 +4889,7 @@ static void R_View_UpdateEntityVisible (void) ent = r_refdef.scene.entities[i]; if (!(ent->flags & renderimask)) if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) - 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)) + if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | 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; } } @@ -4929,7 +4910,7 @@ static void R_View_UpdateEntityVisible (void) 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] == '*'))) + if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*'))) { samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer; if (samples < 0) @@ -4944,7 +4925,7 @@ static void R_View_UpdateEntityVisible (void) } /// only used if skyrendermasked, and normally returns false -int R_DrawBrushModelsSky (void) +static int R_DrawBrushModelsSky (void) { int i, sky; entity_render_t *ent; @@ -5038,19 +5019,36 @@ static void R_DrawModelsAddWaterPlanes(void) } } +static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}}; + void R_HDR_UpdateIrisAdaptation(const vec3_t point) { if (r_hdr_irisadaptation.integer) { + vec3_t p; vec3_t ambient; vec3_t diffuse; vec3_t diffusenormal; - vec_t brightness; + vec3_t forward; + vec_t brightness = 0.0f; vec_t goal; vec_t current; - R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); - brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f); - brightness = max(0.0000001f, brightness); + vec_t d; + int c; + VectorCopy(r_refdef.view.forward, forward); + for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++) + { + p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value; + p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value; + p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value; + R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT); + d = DotProduct(forward, diffusenormal); + brightness += VectorLength(ambient); + if (d > 0) + brightness += d * VectorLength(diffuse); + } + brightness *= 1.0f / c; + brightness += 0.00001f; // make sure it's never zero goal = r_hdr_irisadaptation_multiplier.value / brightness; goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value); current = r_hdr_irisadaptation_value.value; @@ -5268,27 +5266,29 @@ static void R_View_SetFrustum(const int *scissor) //PlaneClassify(&frustum[4]); } -void R_View_UpdateWithScissor(const int *myscissor) +static void R_View_UpdateWithScissor(const int *myscissor) { R_Main_ResizeViewCache(); R_View_SetFrustum(myscissor); R_View_WorldVisibility(r_refdef.view.useclipplane); R_View_UpdateEntityVisible(); R_View_UpdateEntityLighting(); + R_AnimCache_CacheVisibleEntities(); } -void R_View_Update(void) +static void R_View_Update(void) { R_Main_ResizeViewCache(); R_View_SetFrustum(NULL); R_View_WorldVisibility(r_refdef.view.useclipplane); R_View_UpdateEntityVisible(); R_View_UpdateEntityLighting(); + R_AnimCache_CacheVisibleEntities(); } float viewscalefpsadjusted = 1.0f; -void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight) +static 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); @@ -5296,19 +5296,11 @@ void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight) *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) +void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { const float *customclipplane = NULL; float plane[4]; - int scaledwidth, scaledheight; + int /*rtwidth,*/ rtheight, scaledwidth, scaledheight; if (r_refdef.view.useclipplane && allowwaterclippingplane) { // LordHavoc: couldn't figure out how to make this approach the @@ -5323,14 +5315,17 @@ void R_SetupView(qboolean allowwaterclippingplane) if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane; } + //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width; + rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height; + 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 - 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); + R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - 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 - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, 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, rtheight - 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 - 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_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - 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_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL); R_SetViewport(&r_refdef.view.viewport); if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT) { @@ -5387,14 +5382,14 @@ void R_EntityMatrix(const matrix4x4_t *matrix) } } -void R_ResetViewRendering2D(void) +void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { r_viewport_t viewport; DrawQ_Finish(); // 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_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL); R_SetViewport(&viewport); GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); GL_Color(1, 1, 1, 1); @@ -5427,11 +5422,11 @@ void R_ResetViewRendering2D(void) GL_CullFace(GL_NONE); } -void R_ResetViewRendering3D(void) +void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { DrawQ_Finish(); - R_SetupView(true); + R_SetupView(true, fbo, depthtexture, colortexture); GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); GL_Color(1, 1, 1, 1); GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1); @@ -5479,14 +5474,15 @@ static void R_RenderView_UpdateViewVectors(void) Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix); } -void R_RenderScene(void); -void R_RenderWaterPlanes(void); +void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture); +void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture); static void R_Water_StartFrame(void) { int i; int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight; r_waterstate_waterplane_t *p; + qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2; if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d) return; @@ -5530,82 +5526,103 @@ static void R_Water_StartFrame(void) } // allocate textures as needed - if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight) + if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo)) { - r_waterstate.maxwaterplanes = MAX_WATERPLANES; - for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++) + r_fb.water.maxwaterplanes = MAX_WATERPLANES; + for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++) { if (p->texture_refraction) R_FreeTexture(p->texture_refraction); p->texture_refraction = NULL; + if (p->fbo_refraction) + R_Mesh_DestroyFramebufferObject(p->fbo_refraction); + p->fbo_refraction = 0; if (p->texture_reflection) R_FreeTexture(p->texture_reflection); p->texture_reflection = NULL; + if (p->fbo_reflection) + R_Mesh_DestroyFramebufferObject(p->fbo_reflection); + p->fbo_reflection = 0; if (p->texture_camera) R_FreeTexture(p->texture_camera); p->texture_camera = NULL; + if (p->fbo_camera) + R_Mesh_DestroyFramebufferObject(p->fbo_camera); + p->fbo_camera = 0; } - memset(&r_waterstate, 0, sizeof(r_waterstate)); - r_waterstate.texturewidth = texturewidth; - r_waterstate.textureheight = textureheight; - r_waterstate.camerawidth = camerawidth; - r_waterstate.cameraheight = cameraheight; + memset(&r_fb.water, 0, sizeof(r_fb.water)); + r_fb.water.texturewidth = texturewidth; + r_fb.water.textureheight = textureheight; + r_fb.water.camerawidth = camerawidth; + r_fb.water.cameraheight = cameraheight; } - if (r_waterstate.texturewidth) + if (r_fb.water.texturewidth) { int scaledwidth, scaledheight; - r_waterstate.enabled = true; + r_fb.water.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); + // water resolution is usually reduced + r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width); + r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height); + R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight); // set up variables that will be used in shader setup - 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_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth; + r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight; + r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth; + r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight; } - r_waterstate.maxwaterplanes = MAX_WATERPLANES; - r_waterstate.numwaterplanes = 0; + r_fb.water.maxwaterplanes = MAX_WATERPLANES; + r_fb.water.numwaterplanes = 0; } void R_Water_AddWaterPlane(msurface_t *surface, int entno) { - int triangleindex, planeindex; - const int *e; - vec3_t vert[3]; - vec3_t normal; - vec3_t center; + int planeindex, bestplaneindex, vertexindex; + vec3_t mins, maxs, normal, center, v, n; + vec_t planescore, bestplanescore; mplane_t plane; r_waterstate_waterplane_t *p; texture_t *t = R_GetCurrentTexture(surface->texture); - // just use the first triangle with a valid normal for any decisions - VectorClear(normal); - for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3) - { - Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]); - Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]); - Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]); - TriangleNormal(vert[0], vert[1], vert[2], normal); - if (VectorLength2(normal) >= 0.001) - break; - } + rsurface.texture = t; + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface)); + // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway + if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1) + return; + // average the vertex normals, find the surface bounds (after deformvertexes) + Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v); + Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n); + VectorCopy(n, normal); + VectorCopy(v, mins); + VectorCopy(v, maxs); + for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++) + { + Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v); + Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n); + VectorAdd(normal, n, normal); + mins[0] = min(mins[0], v[0]); + mins[1] = min(mins[1], v[1]); + mins[2] = min(mins[2], v[2]); + maxs[0] = max(maxs[0], v[0]); + maxs[1] = max(maxs[1], v[1]); + maxs[2] = max(maxs[2], v[2]); + } + VectorNormalize(normal); + VectorMAM(0.5f, mins, 0.5f, maxs, center); VectorCopy(normal, plane.normal); VectorNormalize(plane.normal); - plane.dist = DotProduct(vert[0], plane.normal); + plane.dist = DotProduct(center, plane.normal); PlaneClassify(&plane); if (PlaneDiff(r_refdef.view.origin, &plane) < 0) { // skip backfaces (except if nocullface is set) - if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE)) - return; +// if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE)) +// return; VectorNegate(plane.normal, plane.normal); plane.dist *= -1; PlaneClassify(&plane); @@ -5613,42 +5630,52 @@ void R_Water_AddWaterPlane(msurface_t *surface, int entno) // find a matching plane if there is one - for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) + bestplaneindex = -1; + bestplanescore = 1048576.0f; + for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++) + { if(p->camera_entity == t->camera_entity) - if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1) - break; - if (planeindex >= r_waterstate.maxwaterplanes) - return; // nothing we can do, out of planes + { + planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f; + if (bestplaneindex < 0 || bestplanescore > planescore) + { + bestplaneindex = planeindex; + bestplanescore = planescore; + } + } + } + planeindex = bestplaneindex; + p = r_fb.water.waterplanes + planeindex; - // if this triangle does not fit any known plane rendered this frame, add one - if (planeindex >= r_waterstate.numwaterplanes) + // if this surface does not fit any known plane rendered this frame, add one + if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes) { // store the new plane - r_waterstate.numwaterplanes++; + planeindex = r_fb.water.numwaterplanes++; + p = r_fb.water.waterplanes + planeindex; p->plane = plane; // clear materialflags and pvs p->materialflags = 0; p->pvsvalid = false; p->camera_entity = t->camera_entity; - VectorCopy(surface->mins, p->mins); - VectorCopy(surface->maxs, p->maxs); + VectorCopy(mins, p->mins); + VectorCopy(maxs, p->maxs); } else { - // merge mins/maxs - p->mins[0] = min(p->mins[0], surface->mins[0]); - p->mins[1] = min(p->mins[1], surface->mins[1]); - p->mins[2] = min(p->mins[2], surface->mins[2]); - p->maxs[0] = max(p->maxs[0], surface->maxs[0]); - p->maxs[1] = max(p->maxs[1], surface->maxs[1]); - p->maxs[2] = max(p->maxs[2], surface->maxs[2]); + // merge mins/maxs when we're adding this surface to the plane + p->mins[0] = min(p->mins[0], mins[0]); + p->mins[1] = min(p->mins[1], mins[1]); + p->mins[2] = min(p->mins[2], mins[2]); + p->maxs[0] = max(p->maxs[0], maxs[0]); + p->maxs[1] = max(p->maxs[1], maxs[1]); + p->maxs[2] = max(p->maxs[2], maxs[2]); } // merge this surface's materialflags into the waterplane p->materialflags |= t->currentmaterialflags; if(!(p->materialflags & MATERIALFLAG_CAMERA)) { // merge this surface's PVS into the waterplane - VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center); if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0) { @@ -5661,7 +5688,7 @@ 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) +static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { int myscissor[4]; r_refdef_view_t originalview; @@ -5669,6 +5696,8 @@ static void R_Water_ProcessPlanes(void) 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; + qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2; + char vabuf[1024]; originalview = r_refdef.view; @@ -5697,48 +5726,69 @@ static void R_Water_ProcessPlanes(void) } // make sure enough textures are allocated - for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) + for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++) { if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) { if (!p->texture_refraction) - p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); if (!p->texture_refraction) goto error; + if (usewaterfbo) + { + if (r_fb.water.depthtexture == NULL) + r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false); + if (p->fbo_refraction == 0) + p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL); + } } else if (p->materialflags & MATERIALFLAG_CAMERA) { if (!p->texture_camera) - p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL); + p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL); if (!p->texture_camera) goto error; + if (usewaterfbo) + { + if (r_fb.water.depthtexture == NULL) + r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false); + if (p->fbo_camera == 0) + p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL); + } } if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) { if (!p->texture_reflection) - p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); if (!p->texture_reflection) goto error; + if (usewaterfbo) + { + if (r_fb.water.depthtexture == NULL) + r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false); + if (p->fbo_reflection == 0) + p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL); + } } } // render views r_refdef.view = originalview; r_refdef.view.showdebug = false; - r_refdef.view.width = r_waterstate.waterwidth; - r_refdef.view.height = r_waterstate.waterheight; + r_refdef.view.width = r_fb.water.waterwidth; + r_refdef.view.height = r_fb.water.waterheight; r_refdef.view.useclipplane = true; myview = r_refdef.view; - r_waterstate.renderingscene = true; - for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) + r_fb.water.renderingscene = true; + for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++) { if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) { r_refdef.view = myview; if(r_water_scissormode.integer) { - R_SetupView(true); + R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection); if(R_ScissorForBBox(p->mins, p->maxs, myscissor)) continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible } @@ -5760,7 +5810,8 @@ static void R_Water_ProcessPlanes(void) memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes); } - R_ResetViewRendering3D(); + r_fb.water.hideplayer = r_water_hideplayer.integer >= 2; + R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection); R_ClearScreen(r_refdef.fogenabled); if(r_water_scissormode.integer & 2) R_View_UpdateWithScissor(myscissor); @@ -5768,9 +5819,11 @@ static void R_Water_ProcessPlanes(void) R_View_Update(); if(r_water_scissormode.integer & 1) GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]); - R_RenderScene(); + R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection); - R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + if (!p->fbo_reflection) + R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_fb.water.hideplayer = false; } // render the normal view scene and copy into texture @@ -5780,12 +5833,12 @@ static void R_Water_ProcessPlanes(void) r_refdef.view = myview; if(r_water_scissormode.integer) { - R_SetupView(true); + R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction); if(R_ScissorForBBox(p->mins, p->maxs, myscissor)) continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible } - r_waterstate.renderingrefraction = true; + r_fb.water.hideplayer = r_water_hideplayer.integer >= 1; r_refdef.view.clipplane = p->plane; VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal); @@ -5794,7 +5847,7 @@ static void R_Water_ProcessPlanes(void) if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity) { // we need to perform a matrix transform to render the view... so let's get the transformation matrix - r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones + r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin); R_RenderView_UpdateViewVectors(); if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS) @@ -5806,7 +5859,7 @@ static void R_Water_ProcessPlanes(void) PlaneClassify(&r_refdef.view.clipplane); - R_ResetViewRendering3D(); + R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction); R_ClearScreen(r_refdef.fogenabled); if(r_water_scissormode.integer & 2) R_View_UpdateWithScissor(myscissor); @@ -5814,10 +5867,11 @@ static void R_Water_ProcessPlanes(void) R_View_Update(); if(r_water_scissormode.integer & 1) GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]); - R_RenderScene(); + R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction); - R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); - r_waterstate.renderingrefraction = false; + if (!p->fbo_refraction) + R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_fb.water.hideplayer = false; } else if (p->materialflags & MATERIALFLAG_CAMERA) { @@ -5827,10 +5881,12 @@ static void R_Water_ProcessPlanes(void) VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal); r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist; - r_refdef.view.width = r_waterstate.camerawidth; - r_refdef.view.height = r_waterstate.cameraheight; + r_refdef.view.width = r_fb.water.camerawidth; + r_refdef.view.height = r_fb.water.cameraheight; r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0); r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0); + r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView + r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView if(p->camera_entity) { @@ -5858,26 +5914,30 @@ static void R_Water_ProcessPlanes(void) PlaneClassify(&r_refdef.view.clipplane); - R_ResetViewRendering3D(); + r_fb.water.hideplayer = false; + + R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera); R_ClearScreen(r_refdef.fogenabled); R_View_Update(); - R_RenderScene(); + R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera); - R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); - r_waterstate.renderingrefraction = false; + if (!p->fbo_camera) + R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_fb.water.hideplayer = false; } } if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1); - r_waterstate.renderingscene = false; + r_fb.water.renderingscene = false; r_refdef.view = originalview; - R_ResetViewRendering3D(); - R_ClearScreen(r_refdef.fogenabled); + R_ResetViewRendering3D(fbo, depthtexture, colortexture); + if (!r_fb.water.depthtexture) + R_ClearScreen(r_refdef.fogenabled); R_View_Update(); goto finish; error: r_refdef.view = originalview; - r_waterstate.renderingscene = false; + r_fb.water.renderingscene = false; Cvar_SetValueQuick(&r_water, 0); Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n"); finish: @@ -5899,11 +5959,33 @@ finish: } } -void R_Bloom_StartFrame(void) +static void R_Bloom_StartFrame(void) { + int i; int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight; int viewwidth, viewheight; - textype_t textype; + qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2; + textype_t 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; + } if (r_viewscale_fpsscaling.integer) { @@ -5941,145 +6023,152 @@ void R_Bloom_StartFrame(void) // set bloomwidth and bloomheight to the bloom resolution that will be // used (often less than the screen resolution for faster rendering) - r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height); - r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width; - r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height); - r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d); - r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d); + r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height); + r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width; + r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height); + r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d); + r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d); // calculate desired texture sizes if (vid.support.arb_texture_non_power_of_two) { screentexturewidth = vid.width; screentextureheight = vid.height; - bloomtexturewidth = r_bloomstate.bloomwidth; - bloomtextureheight = r_bloomstate.bloomheight; + bloomtexturewidth = r_fb.bloomwidth; + bloomtextureheight = r_fb.bloomheight; } else { - for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2); - for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2); - for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2); - for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2); + for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2); + for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2); + for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2); + for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2); } - if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d)) + if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d)) { - Cvar_SetValueQuick(&r_hdr, 0); Cvar_SetValueQuick(&r_bloom, 0); Cvar_SetValueQuick(&r_motionblur, 0); 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)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer) + if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) + && !r_bloom.integer + && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) + && !useviewfbo + && r_viewscale.value == 1.0f + && !r_viewscale_fpsscaling.integer) screentexturewidth = screentextureheight = 0; - if (!r_hdr.integer && !r_bloom.integer) + if (!r_bloom.integer) bloomtexturewidth = bloomtextureheight = 0; - textype = TEXTYPE_COLORBUFFER; - switch (vid.renderpath) + // allocate textures as needed + if (r_fb.screentexturewidth != screentexturewidth + || r_fb.screentextureheight != screentextureheight + || r_fb.bloomtexturewidth != bloomtexturewidth + || r_fb.bloomtextureheight != bloomtextureheight + || r_fb.textype != textype + || useviewfbo != (r_fb.fbo != 0)) { - case RENDERPATH_GL20: - case RENDERPATH_GLES2: - if (vid.support.ext_framebuffer_object) + for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++) { - if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F; - if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F; + if (r_fb.bloomtexture[i]) + R_FreeTexture(r_fb.bloomtexture[i]); + r_fb.bloomtexture[i] = NULL; + + if (r_fb.bloomfbo[i]) + R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]); + r_fb.bloomfbo[i] = 0; } - 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 - || 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, 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); + if (r_fb.fbo) + R_Mesh_DestroyFramebufferObject(r_fb.fbo); + r_fb.fbo = 0; + + if (r_fb.colortexture) + R_FreeTexture(r_fb.colortexture); + r_fb.colortexture = NULL; + + if (r_fb.depthtexture) + R_FreeTexture(r_fb.depthtexture); + r_fb.depthtexture = NULL; + + if (r_fb.ghosttexture) + R_FreeTexture(r_fb.ghosttexture); + r_fb.ghosttexture = NULL; + + r_fb.screentexturewidth = screentexturewidth; + r_fb.screentextureheight = screentextureheight; + r_fb.bloomtexturewidth = bloomtexturewidth; + r_fb.bloomtextureheight = bloomtextureheight; + r_fb.textype = textype; + + if (r_fb.screentexturewidth && r_fb.screentextureheight) + { + if (r_motionblur.value > 0 || r_damageblur.value > 0) + r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + r_fb.ghosttexture_valid = false; + r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + if (useviewfbo) + { + // FIXME: choose depth bits based on a cvar + r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false); + r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL); + R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL); #ifndef USE_GLES2 - // render depth into one texture and normalmap into the other - if (qglDrawBuffer) + // render depth into one texture and color into the other + if (qglDrawBuffer) + { + int status; + qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR + qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR + status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR + if (status != GL_FRAMEBUFFER_COMPLETE) + Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status); + } +#endif + } + } + + if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight) + { + for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++) { - int status; - qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR - qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR - status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR - if (status != GL_FRAMEBUFFER_COMPLETE) - Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status); + r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL); + if (useviewfbo) + r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL); } -#endif } - 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, 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 - r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height); - r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width; - r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height); - r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth); - r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight); + // bloom texture is a different resolution + r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height); + r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width; + r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height); + r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth); + r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight); // 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)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; + r_fb.screentexcoord2f[0] = 0; + r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight; + r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth; + r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight; + r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth; + r_fb.screentexcoord2f[5] = 0; + r_fb.screentexcoord2f[6] = 0; + r_fb.screentexcoord2f[7] = 0; // set up a texcoord array for the reduced resolution bloom image // (which will be additive blended over the screen image) - r_bloomstate.bloomtexcoord2f[0] = 0; - r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight; - r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; - r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight; - r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; - r_bloomstate.bloomtexcoord2f[5] = 0; - r_bloomstate.bloomtexcoord2f[6] = 0; - r_bloomstate.bloomtexcoord2f[7] = 0; + r_fb.bloomtexcoord2f[0] = 0; + r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight; + r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth; + r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight; + r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth; + r_fb.bloomtexcoord2f[5] = 0; + r_fb.bloomtexcoord2f[6] = 0; + r_fb.bloomtexcoord2f[7] = 0; switch(vid.renderpath) { @@ -6097,35 +6186,41 @@ void R_Bloom_StartFrame(void) int i; for (i = 0;i < 4;i++) { - r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth; - r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight; - r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth; - r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight; + r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth; + r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight; + r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth; + r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight; } } break; } - if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth) - { - r_bloomstate.enabled = true; - r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer; - } + R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL); - 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) + if (r_fb.fbo) r_refdef.view.clear = true; } -void R_Bloom_CopyBloomTexture(float colorscale) +static void R_Bloom_MakeTexture(void) { + int x, range, dir; + float xoffset, yoffset, r, brighten; + rtexture_t *intex; + float colorscale = r_bloom_colorscale.value; + r_refdef.stats.bloom++; + if (!r_fb.fbo) + { + R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + } + // scale down screen texture to the bloom texture size CHECKGLERROR - R_Mesh_SetMainRenderTargets(); - R_SetViewport(&r_bloomstate.viewport); + r_fb.bloomindex = 0; + R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL); + R_SetViewport(&r_fb.bloomviewport); GL_BlendFunc(GL_ONE, GL_ZERO); GL_Color(colorscale, colorscale, colorscale, 1); // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that... @@ -6137,90 +6232,81 @@ void R_Bloom_CopyBloomTexture(float colorscale) case RENDERPATH_GLES1: case RENDERPATH_GLES2: case RENDERPATH_SOFT: - R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f); + R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f); break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: case RENDERPATH_D3D11: - R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f); + R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f); break; } // TODO: do boxfilter scale-down in shader? - R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true); + R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, 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; + r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight; - // we now have a bloom image in the framebuffer - // copy it into the bloom image texture for later processing - R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height); - r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height; -} - -void R_Bloom_CopyHDRTexture(void) -{ - R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); - r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; -} - -void R_Bloom_MakeTexture(void) -{ - int x, range, dir; - float xoffset, yoffset, r, brighten; - - r_refdef.stats.bloom++; - - R_ResetViewRendering2D(); - - // we have a bloom image in the framebuffer - CHECKGLERROR - R_SetViewport(&r_bloomstate.viewport); + // we now have a properly scaled bloom image + if (!r_fb.bloomfbo[r_fb.bloomindex]) + { + // copy it into the bloom texture + R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height); + r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height; + } + // multiply bloom image by itself as many times as desired for (x = 1;x < min(r_bloom_colorexponent.value, 32);) { + intex = r_fb.bloomtexture[r_fb.bloomindex]; + r_fb.bloomindex ^= 1; + R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL); x *= 2; r = bound(0, r_bloom_colorexponent.value / x, 1); 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, false, true); + R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f); + R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); - r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; + r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight; - // copy the vertically blurred bloom view to a texture - R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height); - r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height; + if (!r_fb.bloomfbo[r_fb.bloomindex]) + { + // copy the darkened image to a texture + R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height); + r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height; + } } - range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320; + range = r_bloom_blur.integer * r_fb.bloomwidth / 320; brighten = r_bloom_brighten.value; - 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, false, true); for (dir = 0;dir < 2;dir++) { + intex = r_fb.bloomtexture[r_fb.bloomindex]; + r_fb.bloomindex ^= 1; + R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL); // blend on at multiple vertical offsets to achieve a vertical blur // TODO: do offset blends using GLSL // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges GL_BlendFunc(GL_ONE, GL_ZERO); + R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false); for (x = -range;x <= range;x++) { if (!dir){xoffset = 0;yoffset = x;} else {xoffset = x;yoffset = 0;} - xoffset /= (float)r_bloomstate.bloomtexturewidth; - yoffset /= (float)r_bloomstate.bloomtextureheight; + xoffset /= (float)r_fb.bloomtexturewidth; + yoffset /= (float)r_fb.bloomtextureheight; // compute a texcoord array with the specified x and y offset - r_bloomstate.offsettexcoord2f[0] = xoffset+0; - r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight; - r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; - r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight; - r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth; - r_bloomstate.offsettexcoord2f[5] = yoffset+0; - r_bloomstate.offsettexcoord2f[6] = xoffset+0; - r_bloomstate.offsettexcoord2f[7] = yoffset+0; + r_fb.offsettexcoord2f[0] = xoffset+0; + r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight; + r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth; + r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight; + r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth; + r_fb.offsettexcoord2f[5] = yoffset+0; + r_fb.offsettexcoord2f[6] = xoffset+0; + r_fb.offsettexcoord2f[7] = yoffset+0; // this r value looks like a 'dot' particle, fading sharply to // black at the edges // (probably not realistic but looks good enough) @@ -6230,79 +6316,22 @@ void R_Bloom_MakeTexture(void) if(range >= 1) r *= (1 - x*x/(float)(range*range)); GL_Color(r, r, r, 1); - R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f); + R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); - r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight; + r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight; GL_BlendFunc(GL_ONE, GL_ONE); } - // copy the vertically blurred bloom view to a texture - R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height); - r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height; + if (!r_fb.bloomfbo[r_fb.bloomindex]) + { + // copy the vertically or horizontally blurred bloom view to a texture + R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height); + r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height; + } } } -void R_HDR_RenderBloomTexture(void) -{ - int oldwidth, oldheight; - float oldcolorscale; - qboolean oldwaterstate; - - oldwaterstate = r_waterstate.enabled; - oldcolorscale = r_refdef.view.colorscale; - oldwidth = r_refdef.view.width; - oldheight = r_refdef.view.height; - r_refdef.view.width = r_bloomstate.bloomwidth; - r_refdef.view.height = r_bloomstate.bloomheight; - - if(r_hdr.integer < 2) - r_waterstate.enabled = false; - - // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance. - // TODO: add exposure compensation features - // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object) - - r_refdef.view.showdebug = false; - r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16); - - R_ResetViewRendering3D(); - - R_ClearScreen(r_refdef.fogenabled); - if (r_timereport_active) - R_TimeReport("HDRclear"); - - R_View_Update(); - if (r_timereport_active) - R_TimeReport("visibility"); - - // only do secondary renders with HDR if r_hdr is 2 or higher - r_waterstate.numwaterplanes = 0; - if (r_waterstate.enabled) - R_RenderWaterPlanes(); - - r_refdef.view.showdebug = true; - R_RenderScene(); - r_waterstate.numwaterplanes = 0; - - R_ResetViewRendering2D(); - - R_Bloom_CopyHDRTexture(); - R_Bloom_MakeTexture(); - - // restore the view settings - r_waterstate.enabled = oldwaterstate; - r_refdef.view.width = oldwidth; - r_refdef.view.height = oldheight; - r_refdef.view.colorscale = oldcolorscale; - - R_ResetViewRendering3D(); - - R_ClearScreen(r_refdef.fogenabled); - if (r_timereport_active) - R_TimeReport("viewclear"); -} - -static void R_BlendView(void) +static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { unsigned int permutation; float uservecs[4][4]; @@ -6316,21 +6345,21 @@ static void R_BlendView(void) case RENDERPATH_SOFT: case RENDERPATH_GLES2: permutation = - (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0) + (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0) | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0) | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0) | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0) | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0); - if (r_bloomstate.texture_screen) + if (r_fb.colortexture) { - // make sure the buffer is available - if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); } - - R_ResetViewRendering2D(); - R_Mesh_SetMainRenderTargets(); + if (!r_fb.fbo) + { + R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + } - if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0)) + if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture) { // declare variables float blur_factor, blur_mouseaccel, blur_velocity; @@ -6348,10 +6377,10 @@ static void R_BlendView(void) // from the goal, pick an averaged value between goal and last value cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1); blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha; - + // enforce minimum amount of blur blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value; - + //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel); // calculate values into a standard alpha @@ -6364,13 +6393,14 @@ static void R_BlendView(void) / max(0.0001, cl.time - cl.oldtime) // fps independent ); - + // randomization for the blur value to combat persistent ghosting cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value); cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value); - + // apply the blur - if (cl.motionbluralpha > 0 && !r_refdef.envmap) + R_ResetViewRendering2D(fbo, depthtexture, colortexture); + if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid) { GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_Color(1, 1, 1, cl.motionbluralpha); @@ -6382,48 +6412,47 @@ static void R_BlendView(void) case RENDERPATH_GLES1: case RENDERPATH_GLES2: case RENDERPATH_SOFT: - R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f); + R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f); break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: case RENDERPATH_D3D11: - R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f); + R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f); break; } - R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true); + R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, 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; } - - // updates old view angles for next pass + + // updates old view angles for next pass VectorCopy(cl.viewangles, blur_oldangles); - } - // copy view into the screen texture - R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); - r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + // copy view into the ghost texture + R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height); + r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height; + r_fb.ghosttexture_valid = true; + } } - else if (!r_bloomstate.texture_bloom) + else { + // no r_fb.colortexture means we're rendering to the real fb // we may still have to do view tint... if (r_refdef.viewblend[3] >= (1.0f / 256.0f)) { // apply a color tint to the whole view - R_ResetViewRendering2D(); + R_ResetViewRendering2D(0, NULL, NULL); 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, false, true); + R_SetupShader_Generic_NoTexture(false, true); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); } break; // no screen processing, no bloom, skip it } - if (r_bloomstate.texture_bloom && !r_bloomstate.hdr) + if (r_fb.bloomtexture[0]) { - // render simple bloom effect - // copy the screen and shrink it and darken it for the bloom process - R_Bloom_CopyBloomTexture(r_bloom_colorscale.value); // make the bloom texture R_Bloom_MakeTexture(); } @@ -6441,7 +6470,7 @@ static void R_BlendView(void) if (r_glsl_postprocess_uservec4_enable.integer) sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]); - R_ResetViewRendering2D(); + R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer! GL_Color(1, 1, 1, 1); GL_BlendFunc(GL_ONE, GL_ZERO); @@ -6449,13 +6478,13 @@ static void R_BlendView(void) { case RENDERPATH_GL20: case RENDERPATH_GLES2: - R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f); + R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f); R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation); - if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen); - if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom ); + if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture); + if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]); if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps ); if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); - if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight); + if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight); if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]); if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]); if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]); @@ -6467,13 +6496,13 @@ static void R_BlendView(void) case RENDERPATH_D3D9: #ifdef SUPPORTD3D // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that... - R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f); + R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f); R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation); - R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen); - R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom ); + R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture); + R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]); R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps ); hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); - hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight); + hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight); hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]); hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]); hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]); @@ -6490,13 +6519,13 @@ static void R_BlendView(void) Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); break; case RENDERPATH_SOFT: - R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f); + R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f); R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation); - R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen); - R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom ); + R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture); + R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]); R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps ); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); - DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight); + DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]); DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]); @@ -6517,10 +6546,10 @@ static void R_BlendView(void) if (r_refdef.viewblend[3] >= (1.0f / 256.0f)) { // apply a color tint to the whole view - R_ResetViewRendering2D(); + R_ResetViewRendering2D(0, NULL, NULL); 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, false, true); + R_SetupShader_Generic_NoTexture(false, true); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); } @@ -6530,67 +6559,9 @@ static void R_BlendView(void) matrix4x4_t r_waterscrollmatrix; -void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale! +void R_UpdateFog(void) { - if (r_refdef.fog_density) - { - r_refdef.fogcolor[0] = r_refdef.fog_red; - r_refdef.fogcolor[1] = r_refdef.fog_green; - r_refdef.fogcolor[2] = r_refdef.fog_blue; - - Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height); - r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3]; - r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0; - r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth); - - { - vec3_t fogvec; - VectorCopy(r_refdef.fogcolor, fogvec); - // color.rgb *= ContrastBoost * SceneBrightness; - VectorScale(fogvec, r_refdef.view.colorscale, fogvec); - r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f); - r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f); - r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f); - } - } -} - -void R_UpdateVariables(void) -{ - R_Textures_Frame(); - - r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f); - - r_refdef.farclip = r_farclip_base.value; - if (r_refdef.scene.worldmodel) - r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2; - r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f); - - if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1) - Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1); - r_refdef.polygonfactor = 0; - r_refdef.polygonoffset = 0; - r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1); - r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1); - - r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0; - r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil; - r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer; - r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil; - r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; - if (FAKELIGHT_ENABLED) - { - r_refdef.lightmapintensity *= r_fakelight_intensity.value; - } - if (r_showsurfaces.integer) - { - r_refdef.scene.rtworld = false; - r_refdef.scene.rtworldshadows = false; - r_refdef.scene.rtdlight = false; - r_refdef.scene.rtdlightshadows = false; - r_refdef.lightmapintensity = 0; - } - + // Nehahra fog if (gamemode == GAME_NEHAHRA) { if (gl_fogenable.integer) @@ -6621,12 +6592,11 @@ void R_UpdateVariables(void) } } + // fog parms r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1); r_refdef.fog_start = max(0, r_refdef.fog_start); r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end); - // R_UpdateFogColor(); // why? R_RenderScene does it anyway - if (r_refdef.fog_density && r_drawfog.integer) { r_refdef.fogenabled = true; @@ -6652,6 +6622,66 @@ void R_UpdateVariables(void) else r_refdef.fogenabled = false; + // fog color + if (r_refdef.fog_density) + { + r_refdef.fogcolor[0] = r_refdef.fog_red; + r_refdef.fogcolor[1] = r_refdef.fog_green; + r_refdef.fogcolor[2] = r_refdef.fog_blue; + + Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height); + r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3]; + r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0; + r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth); + + { + vec3_t fogvec; + VectorCopy(r_refdef.fogcolor, fogvec); + // color.rgb *= ContrastBoost * SceneBrightness; + VectorScale(fogvec, r_refdef.view.colorscale, fogvec); + r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f); + r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f); + r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f); + } + } +} + +void R_UpdateVariables(void) +{ + R_Textures_Frame(); + + r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f); + + r_refdef.farclip = r_farclip_base.value; + if (r_refdef.scene.worldmodel) + r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2; + r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f); + + if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1) + Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1); + r_refdef.polygonfactor = 0; + r_refdef.polygonoffset = 0; + r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1); + r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1); + + r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0; + r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil; + r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer; + r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil; + r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1; + if (FAKELIGHT_ENABLED) + { + r_refdef.lightmapintensity *= r_fakelight_intensity.value; + } + if (r_showsurfaces.integer) + { + r_refdef.scene.rtworld = false; + r_refdef.scene.rtworldshadows = false; + r_refdef.scene.rtdlight = false; + r_refdef.scene.rtdlightshadows = false; + r_refdef.lightmapintensity = 0; + } + switch(vid.renderpath) { case RENDERPATH_GL20: @@ -6734,17 +6764,50 @@ r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype ) } } +static int R_SortEntities_Compare(const void *ap, const void *bp) +{ + const entity_render_t *a = *(const entity_render_t **)ap; + const entity_render_t *b = *(const entity_render_t **)bp; + + // 1. compare model + if(a->model < b->model) + return -1; + if(a->model > b->model) + return +1; + + // 2. compare skin + // TODO possibly calculate the REAL skinnum here first using + // skinscenes? + if(a->skinnum < b->skinnum) + return -1; + if(a->skinnum > b->skinnum) + return +1; + + // everything we compared is equal + return 0; +} +static void R_SortEntities(void) +{ + // below or equal 2 ents, sorting never gains anything + if(r_refdef.scene.numentities <= 2) + return; + // sort + qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare); +} + /* ================ 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; + int fbo; + rtexture_t *depthtexture; + rtexture_t *colortexture; dpsoftrast_test = r_test.integer; @@ -6758,6 +6821,8 @@ void R_RenderView(void) if (!r_drawentities.integer) r_refdef.scene.numentities = 0; + else if (r_sortentities.integer) + R_SortEntities(); R_AnimCache_ClearCache(); R_FrameData_NewFrame(); @@ -6772,15 +6837,16 @@ void R_RenderView(void) if (r_refdef.view.isoverlay) { // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas] + R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL); GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0); R_TimeReport("depthclear"); r_refdef.view.showdebug = false; - r_waterstate.enabled = false; - r_waterstate.numwaterplanes = 0; + r_fb.water.enabled = false; + r_fb.water.numwaterplanes = 0; - R_RenderScene(); + R_RenderScene(0, NULL, NULL); r_refdef.view.matrix = originalmatrix; @@ -6791,7 +6857,7 @@ void R_RenderView(void) if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/) { r_refdef.view.matrix = originalmatrix; - return; //Host_Error ("R_RenderView: NULL worldmodel"); + return; } r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value; @@ -6803,13 +6869,18 @@ void R_RenderView(void) R_Bloom_StartFrame(); R_Water_StartFrame(); + // now we probably have an fbo to render into + fbo = r_fb.fbo; + depthtexture = r_fb.depthtexture; + colortexture = r_fb.colortexture; + CHECKGLERROR if (r_timereport_active) R_TimeReport("viewsetup"); - R_ResetViewRendering3D(); + R_ResetViewRendering3D(fbo, depthtexture, colortexture); - if (r_refdef.view.clear || r_refdef.fogenabled) + if (r_refdef.view.clear || r_refdef.fogenabled || fbo) { R_ClearScreen(r_refdef.fogenabled); if (r_timereport_active) @@ -6817,14 +6888,6 @@ void R_RenderView(void) } r_refdef.view.clear = true; - // this produces a bloom texture to be used in R_BlendView() later - 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 - r_textureframe++; // used only by R_GetCurrentTexture - } - r_refdef.view.showdebug = true; R_View_Update(); @@ -6835,14 +6898,14 @@ void R_RenderView(void) if (r_timereport_active && r_shadow_bouncegrid.integer) R_TimeReport("bouncegrid"); - r_waterstate.numwaterplanes = 0; - if (r_waterstate.enabled) - R_RenderWaterPlanes(); + r_fb.water.numwaterplanes = 0; + if (r_fb.water.enabled) + R_RenderWaterPlanes(fbo, depthtexture, colortexture); - R_RenderScene(); - r_waterstate.numwaterplanes = 0; + R_RenderScene(fbo, depthtexture, colortexture); + r_fb.water.numwaterplanes = 0; - R_BlendView(); + R_BlendView(fbo, depthtexture, colortexture); if (r_timereport_active) R_TimeReport("blendview"); @@ -6854,7 +6917,7 @@ void R_RenderView(void) CHECKGLERROR } -void R_RenderWaterPlanes(void) +void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes) { @@ -6871,26 +6934,21 @@ void R_RenderWaterPlanes(void) if (r_timereport_active) R_TimeReport("watermodels"); - if (r_waterstate.numwaterplanes) + if (r_fb.water.numwaterplanes) { - R_Water_ProcessPlanes(); + R_Water_ProcessPlanes(fbo, depthtexture, colortexture); if (r_timereport_active) R_TimeReport("waterscenes"); } } -extern void R_DrawLightningBeams (void); -extern void VM_CL_AddPolygonsToMeshQueue (void); -extern void R_DrawPortals (void); extern cvar_t cl_locs_show; static void R_DrawLocs(void); static void R_DrawEntityBBoxes(void); static void R_DrawModelDecals(void); -extern void R_DrawModelShadows(void); -extern void R_DrawModelShadowMaps(void); extern cvar_t cl_decals_newsystem; extern qboolean r_shadow_usingdeferredprepass; -void R_RenderScene(void) +void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture) { qboolean shadowmapping = false; @@ -6899,7 +6957,7 @@ void R_RenderScene(void) r_refdef.stats.renders++; - R_UpdateFogColor(); + R_UpdateFog(); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) @@ -6933,19 +6991,15 @@ void R_RenderScene(void) if (skyrendermasked && skyrenderlater) { // we have to force off the water clipping plane while rendering sky - R_SetupView(false); + R_SetupView(false, fbo, depthtexture, colortexture); R_Sky(); - R_SetupView(true); + R_SetupView(true, fbo, depthtexture, colortexture); if (r_timereport_active) R_TimeReport("sky"); } } - R_AnimCache_CacheVisibleEntities(); - if (r_timereport_active) - R_TimeReport("animation"); - - R_Shadow_PrepareLights(); + R_Shadow_PrepareLights(fbo, depthtexture, colortexture); if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0) R_Shadow_PrepareModelShadows(); if (r_timereport_active) @@ -6972,8 +7026,9 @@ void R_RenderScene(void) if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0) { - R_DrawModelShadowMaps(); - R_ResetViewRendering3D(); + R_ResetViewRendering3D(fbo, depthtexture, colortexture); + R_DrawModelShadowMaps(fbo, depthtexture, colortexture); + R_ResetViewRendering3D(fbo, depthtexture, colortexture); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) S_ExtraUpdate (); @@ -7000,8 +7055,9 @@ void R_RenderScene(void) if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { - R_DrawModelShadows(); - R_ResetViewRendering3D(); + R_ResetViewRendering3D(fbo, depthtexture, colortexture); + R_DrawModelShadows(fbo, depthtexture, colortexture); + R_ResetViewRendering3D(fbo, depthtexture, colortexture); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) S_ExtraUpdate (); @@ -7020,8 +7076,9 @@ void R_RenderScene(void) if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { - R_DrawModelShadows(); - R_ResetViewRendering3D(); + R_ResetViewRendering3D(fbo, depthtexture, colortexture); + R_DrawModelShadows(fbo, depthtexture, colortexture); + R_ResetViewRendering3D(fbo, depthtexture, colortexture); // don't let sound skip if going slow if (r_refdef.scene.extraupdate) S_ExtraUpdate (); @@ -7055,7 +7112,8 @@ void R_RenderScene(void) R_TimeReport("lightning"); } - VM_CL_AddPolygonsToMeshQueue(); + if (cl.csqc_loaded) + VM_CL_AddPolygonsToMeshQueue(CLVM_prog); if (r_refdef.view.showdebug) { @@ -7129,8 +7187,6 @@ void R_RenderScene(void) // don't let sound skip if going slow if (r_refdef.scene.extraupdate) S_ExtraUpdate (); - - R_ResetViewRendering2D(); } static const unsigned short bboxelements[36] = @@ -7143,7 +7199,7 @@ static const unsigned short bboxelements[36] = 1, 0, 2, 1, 2, 3, }; -void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca) +static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca) { int i; float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4]; @@ -7178,26 +7234,24 @@ 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, false, false); + R_SetupShader_Generic_NoTexture(false, false); R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0); } static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { + prvm_prog_t *prog = SVVM_prog; int i; float color[4]; prvm_edict_t *edict; - prvm_prog_t *prog_save = prog; // this function draws bounding boxes of server entities if (!sv.active) return; GL_CullFace(GL_NONE); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false); + R_SetupShader_Generic_NoTexture(false, false); - prog = 0; - SV_VM_Begin(); for (i = 0;i < numsurfaces;i++) { edict = PRVM_EDICT_NUM(surfacelist[i]); @@ -7216,8 +7270,6 @@ static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtligh GL_CullFace(r_refdef.view.cullface_front); R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]); } - SV_VM_End(); - prog = prog_save; } static void R_DrawEntityBBoxes(void) @@ -7225,14 +7277,12 @@ static void R_DrawEntityBBoxes(void) int i; prvm_edict_t *edict; vec3_t center; - prvm_prog_t *prog_save = prog; + prvm_prog_t *prog = SVVM_prog; // this function draws bounding boxes of server entities if (!sv.active) return; - prog = 0; - SV_VM_Begin(); for (i = 0;i < prog->num_edicts;i++) { edict = PRVM_EDICT_NUM(i); @@ -7246,8 +7296,6 @@ static void R_DrawEntityBBoxes(void) 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); } - SV_VM_End(); - prog = prog_save; } static const int nomodelelement3i[24] = @@ -7294,7 +7342,7 @@ static const float nomodelcolor4f[6*4] = 0.5f, 0.0f, 0.0f, 1.0f }; -void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) +static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { int i; float f1, f2, *c; @@ -7344,7 +7392,7 @@ void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight } } // R_Mesh_ResetTextureState(); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false); + R_SetupShader_Generic_NoTexture(false, false); R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL); R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0); } @@ -7405,7 +7453,7 @@ void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t le vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1; } -int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z) +static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z) { int i; float *vertex3f; @@ -7448,7 +7496,7 @@ void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f) } } -void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d) +static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d) { int i; int *e, element[3]; @@ -7567,7 +7615,7 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) return (float) f; } -void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags) +static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags) { int w, h, idx; double f; @@ -7589,8 +7637,9 @@ void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *t Matrix4x4_CreateTranslate(&matrix, 0, 0, 0); break; case Q3TCMOD_ROTATE: + f = tcmod->parms[0] * rsurface.shadertime; Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0); - Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1); + Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1); Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0); break; case Q3TCMOD_SCALE: @@ -7630,7 +7679,7 @@ void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *t Matrix4x4_Concat(texmatrix, &matrix, &temp); } -void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname) +static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname) { int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP; char name[MAX_QPATH]; @@ -7727,9 +7776,9 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->currentalpha = rsurface.colormod[3]; 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) + if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later - if(!r_waterstate.enabled || r_refdef.view.isoverlay) + if(!r_fb.water.enabled || r_refdef.view.isoverlay) t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA); if (!(rsurface.ent_flags & RENDER_LIGHT)) t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; @@ -7749,6 +7798,9 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; else if (t->currentalpha < 1) t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; + // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags + if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) + t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA); if (rsurface.ent_flags & RENDER_DOUBLESIDED) t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE; if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) @@ -7842,6 +7894,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) } t->specularscale *= t->specularscalemod; t->specularpower *= t->specularpowermod; + t->rtlightambient = 0; // lightmaps mode looks bad with dlights using actual texturing, so turn // off the colormap and glossmap, but leave the normalmap on as it still @@ -8415,7 +8468,7 @@ float RSurf_FogVertex(const float *v) return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)]; } -void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust) +static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust) { int i; for (i = 0;i < numelements;i++) @@ -9322,7 +9375,7 @@ static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface) r_waterstate_waterplane_t *p; qboolean prepared = false; bestd = 0; - for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++) + for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++) { if(p->camera_entity != rsurface.texture->camera_entity) continue; @@ -9655,7 +9708,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, false, false); + R_SetupShader_Generic_NoTexture(false, false); skyrenderlater = true; RSurf_SetupDepthAndCulling(); GL_DepthMask(true); @@ -9684,7 +9737,7 @@ static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_ } else { - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false); + R_SetupShader_Generic_NoTexture(false, false); // fog sky GL_BlendFunc(GL_ONE, GL_ZERO); RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); @@ -9703,7 +9756,7 @@ extern rtexture_t *r_shadow_prepasslightingdiffusetexture; extern rtexture_t *r_shadow_prepasslightingspeculartexture; static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass) { - if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))) + if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))) return; if (prepass) { @@ -9736,7 +9789,7 @@ 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), false); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false); RSurf_DrawBatch(); // blend surface on top GL_DepthMask(false); @@ -9747,7 +9800,7 @@ static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface { // 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), false); + R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false); RSurf_DrawBatch(); } } @@ -9979,7 +10032,7 @@ static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const float c[4]; // R_Mesh_ResetTextureState(); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false); + R_SetupShader_Generic_NoTexture(false, false); if(rsurface.texture && rsurface.texture->currentskinframe) { @@ -10085,7 +10138,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, false, false); + R_SetupShader_Generic_NoTexture(false, false); RSurf_DrawBatch(); } else if (!r_refdef.view.showdebug) @@ -10373,7 +10426,7 @@ static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msu { if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST))) return; - if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))) + if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))) return; RSurf_SetupDepthAndCulling(); RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist); @@ -10417,7 +10470,7 @@ static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurf CHECKGLERROR } -void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass) +static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass) { int i, j; texture_t *texture; @@ -10495,7 +10548,7 @@ static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurf CHECKGLERROR } -void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass) +static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass) { int i, j; texture_t *texture; @@ -10561,7 +10614,7 @@ unsigned short locboxelements[6*2*3] = 20,21,22, 20,22,23 }; -void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) +static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { int i, j; cl_locnode_t *loc = (cl_locnode_t *)ent; @@ -10600,7 +10653,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, false, false); + R_SetupShader_Generic_NoTexture(false, false); R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0); } @@ -11227,7 +11280,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, false, false); + R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false); R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0); } } @@ -11269,7 +11322,7 @@ static void R_DrawModelDecals(void) } extern cvar_t mod_collision_bih; -void R_DrawDebugModel(void) +static void R_DrawDebugModel(void) { entity_render_t *ent = rsurface.entity; int i, j, k, l, flagsmask; @@ -11284,7 +11337,7 @@ void R_DrawDebugModel(void) { 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, false); + R_SetupShader_Generic_NoTexture(false, false); GL_DepthTest(false); GL_DepthMask(false); GL_DepthRange(0, 1); @@ -11314,7 +11367,7 @@ void R_DrawDebugModel(void) flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL; // R_Mesh_ResetTextureState(); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false); + R_SetupShader_Generic_NoTexture(false, false); GL_DepthRange(0, 1); GL_DepthTest(!r_showdisabledepthtest.integer); GL_DepthMask(false); @@ -11484,7 +11537,6 @@ void R_DrawDebugModel(void) #endif } -extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface); int r_maxsurfacelist = 0; const msurface_t **r_surfacelist = NULL; void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)