X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_rmain.c;h=9499f16c8611554e532c5a09f40c1e1b87a71ede;hp=5a0228058b10a3a5b2ff6b7a660272aac4a80c47;hb=5aefe7c200a0278927239cdd4eb56391a66056f1;hpb=0f2c65fd8f40d97b404c587bcd0660e945241ff1 diff --git a/gl_rmain.c b/gl_rmain.c index 5a022805..9499f16c 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -50,8 +50,8 @@ static qboolean r_savedds; // r_refdef_t r_refdef; -cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"}; -cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"}; +cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"}; +cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"}; cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"}; cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"}; cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"}; @@ -132,6 +132,8 @@ cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", 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"}; +cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9 +cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"}; cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"}; @@ -201,6 +203,7 @@ 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_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"}; 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"}; @@ -224,7 +227,7 @@ cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alon cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"}; cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"}; -cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."}; +cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."}; cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"}; @@ -853,8 +856,10 @@ enum SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler + SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math) + SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines) }; -#define SHADERSTATICPARMS_COUNT 11 +#define SHADERSTATICPARMS_COUNT 13 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT]; static int shaderstaticparms_count = 0; @@ -897,6 +902,10 @@ qboolean R_CompileShader_CheckStaticParms(void) R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2); else if (r_shadow_shadowmappcf) R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1); + if (r_celshading.integer) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING); + if (r_celoutlines.integer) + R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES); return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0; } @@ -922,6 +931,8 @@ static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permu R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1"); R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2"); R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING"); + R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES"); } /// information about each possible shader permutation @@ -2172,9 +2183,9 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, else { mode = SHADERMODE_GENERIC; - permutation |= SHADERPERMUTATION_DIFFUSE; - GL_BlendFunc(GL_ONE, GL_ZERO); - blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO); + permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } if (vid.allowalphatocoverage) GL_AlphaToCoverage(false); @@ -3300,7 +3311,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(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, 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, false))) { basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel); if (basepixels == NULL) @@ -3334,7 +3345,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(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, 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, true); //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 @@ -3381,13 +3392,13 @@ skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboole { mymiplevel = savemiplevel; if (r_loadnormalmap) - 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); + 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, true); + skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true); if (r_loadgloss) - 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); + skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true); + skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true); + skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true); + skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true); } // _norm is the name used by tenebrae and has been adopted as standard @@ -3501,7 +3512,7 @@ skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, co // if already loaded just return it, otherwise make a new skinframe 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) + if (skinframe->base) return skinframe; textureflags &= ~TEXF_FORCE_RELOAD; @@ -3571,9 +3582,9 @@ skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, i // 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) : 0, true); - if (skinframe && skinframe->base) + if (skinframe->base) return skinframe; - textureflags &= ~TEXF_FORCE_RELOAD; + //textureflags &= ~TEXF_FORCE_RELOAD; skinframe->stain = NULL; skinframe->merged = NULL; @@ -3695,7 +3706,7 @@ skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, co // 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) : 0, true); - if (skinframe && skinframe->base) + if (skinframe->base) return skinframe; textureflags &= ~TEXF_FORCE_RELOAD; @@ -4263,6 +4274,8 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable); Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable); Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable); + Cvar_RegisterVariable(&r_celshading); + Cvar_RegisterVariable(&r_celoutlines); Cvar_RegisterVariable(&r_water); Cvar_RegisterVariable(&r_water_resolutionmultiplier); @@ -4285,6 +4298,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_bloom_resolution); Cvar_RegisterVariable(&r_bloom_colorexponent); Cvar_RegisterVariable(&r_bloom_colorsubtract); + Cvar_RegisterVariable(&r_bloom_scenebrightness); Cvar_RegisterVariable(&r_hdr_scenebrightness); Cvar_RegisterVariable(&r_hdr_glowintensity); Cvar_RegisterVariable(&r_hdr_irisadaptation); @@ -5281,7 +5295,6 @@ static void R_View_UpdateWithScissor(const int *myscissor) R_View_WorldVisibility(r_refdef.view.useclipplane); R_View_UpdateEntityVisible(); R_View_UpdateEntityLighting(); - R_AnimCache_CacheVisibleEntities(); } static void R_View_Update(void) @@ -5291,7 +5304,6 @@ static void R_View_Update(void) R_View_WorldVisibility(r_refdef.view.useclipplane); R_View_UpdateEntityVisible(); R_View_UpdateEntityLighting(); - R_AnimCache_CacheVisibleEntities(); } float viewscalefpsadjusted = 1.0f; @@ -5835,6 +5847,7 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t R_View_UpdateWithScissor(myscissor); else R_View_Update(); + R_AnimCache_CacheVisibleEntities(); if(r_water_scissormode.integer & 1) GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]); R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection); @@ -5883,6 +5896,7 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t R_View_UpdateWithScissor(myscissor); else R_View_Update(); + R_AnimCache_CacheVisibleEntities(); if(r_water_scissormode.integer & 1) GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]); R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction); @@ -5937,6 +5951,7 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera); R_ClearScreen(r_refdef.fogenabled); R_View_Update(); + R_AnimCache_CacheVisibleEntities(); R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera); if (!p->fbo_camera) @@ -5952,6 +5967,7 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t if (!r_fb.water.depthtexture) R_ClearScreen(r_refdef.fogenabled); R_View_Update(); + R_AnimCache_CacheVisibleEntities(); goto finish; error: r_refdef.view = originalview; @@ -6045,7 +6061,7 @@ static 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_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height); + r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width); 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); @@ -6151,7 +6167,7 @@ static void R_Bloom_StartFrame(void) } // bloom texture is a different resolution - r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height); + r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width); 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); @@ -6168,6 +6184,14 @@ static void R_Bloom_StartFrame(void) r_fb.screentexcoord2f[6] = 0; r_fb.screentexcoord2f[7] = 0; + if(r_fb.fbo) + { + for (i = 1;i < 8;i += 2) + { + r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight; + } + } + // set up a texcoord array for the reduced resolution bloom image // (which will be additive blended over the screen image) r_fb.bloomtexcoord2f[0] = 0; @@ -6191,20 +6215,17 @@ static void R_Bloom_StartFrame(void) case RENDERPATH_D3D9: case RENDERPATH_D3D10: case RENDERPATH_D3D11: + for (i = 0;i < 4;i++) { - int i; - for (i = 0;i < 4;i++) - { - 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; - } + 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; } - 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_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL); if (r_fb.fbo) r_refdef.view.clear = true; @@ -6218,18 +6239,22 @@ static void R_Bloom_MakeTexture(void) float colorscale = r_bloom_colorscale.value; r_refdef.stats.bloom++; - + +#if 0 + // this copy is unnecessary since it happens in R_BlendView already 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; } +#endif // scale down screen texture to the bloom texture size CHECKGLERROR 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_DepthTest(false); 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... @@ -6318,14 +6343,14 @@ static void R_Bloom_MakeTexture(void) xoffset /= (float)r_fb.bloomtexturewidth; yoffset /= (float)r_fb.bloomtextureheight; // compute a texcoord array with the specified x and y offset - 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; + r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0]; + r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1]; + r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2]; + r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3]; + r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4]; + r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5]; + r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6]; + r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7]; // this r value looks like a 'dot' particle, fading sharply to // black at the edges // (probably not realistic but looks good enough) @@ -6895,6 +6920,11 @@ void R_RenderView(void) R_Shadow_UpdateWorldLightSelection(); R_Bloom_StartFrame(); + + // apply bloom brightness offset + if(r_fb.bloomtexture[0]) + r_refdef.view.colorscale *= r_bloom_scenebrightness.value; + R_Water_StartFrame(); // now we probably have an fbo to render into @@ -6922,6 +6952,10 @@ void R_RenderView(void) if (r_timereport_active) R_TimeReport("visibility"); + R_AnimCache_CacheVisibleEntities(); + if (r_timereport_active) + R_TimeReport("animcache"); + R_Shadow_UpdateBounceGridTexture(); if (r_timereport_active && r_shadow_bouncegrid.integer) R_TimeReport("bouncegrid"); @@ -7323,7 +7357,7 @@ static void R_DrawEntityBBoxes(void) if(PRVM_serveredictedict(edict, viewmodelforclient) != 0) continue; VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center); - R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL); + R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL); } } @@ -7431,12 +7465,12 @@ void R_DrawNoModel(entity_render_t *ent) vec3_t org; Matrix4x4_OriginFromMatrix(&ent->matrix, org); if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1)) - R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight); + R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight); else R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL); } -void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width) +void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width) { vec3_t right1, right2, diff, normal; @@ -7739,15 +7773,15 @@ texture_t *R_GetCurrentTexture(texture_t *t) { int i; const entity_render_t *ent = rsurface.entity; - dp_model_t *model = ent->model; + dp_model_t *model = ent->model; // when calling this, ent must not be NULL q3shaderinfo_layer_tcmod_t *tcmod; - if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent) + if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate) return t->currentframe; t->update_lastrenderframe = r_textureframe; t->update_lastrenderentity = (void *)ent; - if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS) + if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS) t->camera_entity = ent->entitynumber; else t->camera_entity = 0; @@ -7891,6 +7925,11 @@ texture_t *R_GetCurrentTexture(texture_t *t) t->backgroundglowtexture = t->backgroundcurrentskinframe->glow; if (!t->backgroundnmaptexture) t->backgroundnmaptexture = r_texture_blanknormalmap; + // make sure that if glow is going to be used, both textures are not NULL + if (!t->backgroundglowtexture && t->glowtexture) + t->backgroundglowtexture = r_texture_black; + if (!t->glowtexture && t->backgroundglowtexture) + t->glowtexture = r_texture_black; } else { @@ -7974,7 +8013,7 @@ texture_t *R_GetCurrentTexture(texture_t *t) blendfunc2 = GL_ZERO; } // don't colormod evilblend textures - if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD) + if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)) VectorSet(t->lightmapcolor, 1, 1, 1); depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED); if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) @@ -8152,6 +8191,7 @@ void RSurf_ActiveWorldEntity(void) rsurface.passcolor4f = NULL; rsurface.passcolor4f_vertexbuffer = NULL; rsurface.passcolor4f_bufferoffset = 0; + rsurface.forcecurrenttextureupdate = false; } void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass) @@ -8325,6 +8365,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q rsurface.passcolor4f = NULL; rsurface.passcolor4f_vertexbuffer = NULL; rsurface.passcolor4f_bufferoffset = 0; + rsurface.forcecurrenttextureupdate = false; } void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents) @@ -8448,6 +8489,7 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve rsurface.passcolor4f = NULL; rsurface.passcolor4f_vertexbuffer = NULL; rsurface.passcolor4f_bufferoffset = 0; + rsurface.forcecurrenttextureupdate = true; if (rsurface.modelnumvertices && rsurface.modelelement3i) { @@ -9458,7 +9500,7 @@ static void RSurf_DrawBatch_GL11_ApplyFog(void) rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4])); rsurface.passcolor4f_vertexbuffer = 0; rsurface.passcolor4f_bufferoffset = 0; - for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4) + for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4) { f = RSurf_FogVertex(v); c2[0] = c[0] * f; @@ -9936,8 +9978,8 @@ static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface R_Mesh_TexBind(1, 0); R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0); // generate a color array for the fog pass - R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0); RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]); + R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0); RSurf_DrawBatch(); break; default: @@ -9979,7 +10021,7 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface switch (layer->type) { case TEXTURELAYERTYPE_LITTEXTURE: - if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO) + if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)) { // two-pass lit texture with 2x rgbscale // first the lightmap pass @@ -10012,6 +10054,8 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog); + else if (FAKELIGHT_ENABLED) + RSurf_DrawBatch_GL11_FakeLight(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog); else RSurf_DrawBatch_GL11_VertexColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog); } @@ -10039,8 +10083,8 @@ static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0); } // generate a color array for the fog pass - R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0); RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]); + R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0); RSurf_DrawBatch(); break; default: @@ -10457,7 +10501,7 @@ static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset; center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset; } - R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight); + R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight); } } @@ -10704,7 +10748,7 @@ void R_DrawLocs(void) for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++) { VectorLerp(loc->mins, 0.5f, loc->maxs, center); - R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL); + R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL); } } @@ -11149,7 +11193,6 @@ static void R_DrawModelDecals_FadeEntity(entity_render_t *ent) else frametime = 0; decalsystem->lastupdatetime = r_refdef.scene.time; - decal = decalsystem->decals; numdecals = decalsystem->numdecals; for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++) @@ -11226,7 +11269,6 @@ static void R_DrawModelDecals_Entity(entity_render_t *ent) RSurf_ActiveModelEntity(ent, false, false, false); decalsystem->lastupdatetime = r_refdef.scene.time; - decal = decalsystem->decals; faderate = 1.0f / max(0.001f, cl_decals_fadetime.value); @@ -11415,13 +11457,12 @@ static void R_DrawDebugModel(void) { int triangleindex; int bihleafindex; - qboolean cullbox = ent == r_refdef.scene.worldentity; + qboolean cullbox = false; const q3mbrush_t *brush; const bih_t *bih = &model->collision_bih; const bih_leaf_t *bihleaf; float vertex3f[3][3]; GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value); - cullbox = false; for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++) { if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs)) @@ -11794,10 +11835,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr } } } - if (update) - for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++) - if (update[j]) - R_BuildLightMap(ent, surfaces + j); + R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass); // add to stats if desired