From: divverent Date: Sun, 6 Mar 2011 18:42:35 +0000 (+0000) Subject: add a hack to support fog on premultiplied alpha surfaces too X-Git-Tag: xonotic-v0.5.0~425^2~2 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=569f8b9b42e9bbaf79a73b8e15c076c0d97c3920;p=xonotic%2Fdarkplaces.git add a hack to support fog on premultiplied alpha surfaces too git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10901 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/dpsoftrast.h b/dpsoftrast.h index d05ce2a4..302d5cf2 100644 --- a/dpsoftrast.h +++ b/dpsoftrast.h @@ -171,28 +171,29 @@ typedef enum shaderpermutation_e SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis - SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only) - SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter - SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture - SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only) - SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects - SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only) - SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface - SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface - SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) - SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter - SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results - SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results - SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test - SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing - SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, ///< (lightsource) use orthographic shadowmap projection - SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping - SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5 - SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe) - SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, ///< (water) counter-direction normalmaps scrolling - SHADERPERMUTATION_BOUNCEGRID = 1<<27, ///< (lightmap) use Texture_BounceGrid as an additional source of ambient light - SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array - SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array + SHADERPERMUTATION_FOGALPHAHACK = 1<<8, ///< fog color and density determined by texture mapped on vertical axis + SHADERPERMUTATION_GAMMARAMPS = 1<<9, ///< gamma (postprocessing only) + SHADERPERMUTATION_CUBEFILTER = 1<<10, ///< (lightsource) use cubemap light filter + SHADERPERMUTATION_GLOW = 1<<11, ///< (lightmap) blend in an additive glow texture + SHADERPERMUTATION_BLOOM = 1<<12, ///< bloom (postprocessing only) + SHADERPERMUTATION_SPECULAR = 1<<13, ///< (lightsource or deluxemapping) render specular effects + SHADERPERMUTATION_POSTPROCESSING = 1<<14, ///< user defined postprocessing (postprocessing only) + SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface + SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface + SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) + SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter + SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results + SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results + SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test + SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing + SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, ///< (lightsource) use orthographic shadowmap projection + SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping + SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5 + SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe) + SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<27, ///< (water) counter-direction normalmaps scrolling + SHADERPERMUTATION_BOUNCEGRID = 1<<28, ///< (lightmap) use Texture_BounceGrid as an additional source of ambient light + SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array + SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array } shaderpermutation_t; diff --git a/fogeval.pl b/fogeval.pl index a3633203..e6262bd1 100644 --- a/fogeval.pl +++ b/fogeval.pl @@ -47,7 +47,7 @@ sub isfogfriendly($$$$$) # 1. blend(fog(s), sa, fog(d), da) # 2. fog(blend(s, sa, d, da)) - my ($out1, $out1a) = evalblend $fs, $fd, $s + ((defined $foghack ? $foghack < 0 ? $s : $foghack : $fogcolor) - $s) * $fogamount, $sa, $d + ($fogcolor - $d) * $fogamount, $da; + my ($out1, $out1a) = evalblend $fs, $fd, $s + ((defined $foghack ? $foghack eq 'ALPHA' ? $fogcolor*$sa : $foghack : $fogcolor) - $s) * $fogamount, $sa, $d + ($fogcolor - $d) * $fogamount, $da; my ($out2, $out2a) = evalblend $fs, $fd, $s, $sa, $d, $da; $out2 = $out2 + ($fogcolor - $out2) * $fogamount; @@ -82,7 +82,7 @@ sub willitfog($$) my ($fs, $fd) = @_; FOGHACK: - for my $foghack(undef, 0, 1, -1) + for my $foghack(undef, 0, 'ALPHA') { for my $s(0, 0.25, 0.5, 0.75, 1) { diff --git a/gl_rmain.c b/gl_rmain.c index 9b973e57..9d43f088 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -633,6 +633,7 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USEFOGINSIDE\n", " foginside"}, {"#define USEFOGOUTSIDE\n", " fogoutside"}, {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"}, + {"#define USEFOGALPHAHACK\n", " fogalphahack"}, {"#define USEGAMMARAMPS\n", " gammaramps"}, {"#define USECUBEFILTER\n", " cubefilter"}, {"#define USEGLOW\n", " glow"}, @@ -1988,10 +1989,11 @@ extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture; extern rtexture_t *r_shadow_prepasslightingdiffusetexture; extern rtexture_t *r_shadow_prepasslightingspeculartexture; -#define BLENDFUNC_ALLOWS_COLORMOD 1 -#define BLENDFUNC_ALLOWS_FOG 2 -#define BLENDFUNC_ALLOWS_FOG_HACK0 4 -#define BLENDFUNC_ALLOWS_ANYFOG 6 +#define BLENDFUNC_ALLOWS_COLORMOD 1 +#define BLENDFUNC_ALLOWS_FOG 2 +#define BLENDFUNC_ALLOWS_FOG_HACK0 4 +#define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8 +#define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA) static int R_BlendFuncFlags(int src, int dst) { int r = 0; @@ -2016,6 +2018,7 @@ static int R_BlendFuncFlags(int src, int dst) if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD; if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD; if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0; + if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA; if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG; if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG; if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0; @@ -2388,6 +2391,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, colormod = dummy_colormod; if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG)) permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE); + if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA) + permutation |= SHADERPERMUTATION_FOGALPHAHACK; switch(vid.renderpath) { case RENDERPATH_D3D9: diff --git a/shader_glsl.h b/shader_glsl.h index 419908be..614fbf4e 100644 --- a/shader_glsl.h +++ b/shader_glsl.h @@ -542,22 +542,26 @@ "uniform highp float FogRangeRecip;\n" "uniform highp float FogPlaneViewDist;\n" "uniform highp float FogHeightFade;\n" -"vec3 FogVertex(vec3 surfacecolor)\n" +"vec3 FogVertex(vec4 surfacecolor)\n" "{\n" " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n" " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n" " float fogfrac;\n" +" vec3 fc = FogColor;\n" +"#ifdef USEFOGALPHAHACK\n" +" fc *= surfacecolor.a;\n" +"#endif\n" "#ifdef USEFOGHEIGHTTEXTURE\n" " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n" " fogfrac = fogheightpixel.a;\n" -" return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n" +" return mix(fogheightpixel.rgb * fc, surfacecolor.rgb, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n" "#else\n" "# ifdef USEFOGOUTSIDE\n" " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n" "# else\n" " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n" "# endif\n" -" return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n" +" return mix(fc, surfacecolor.rgb, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n" "#endif\n" "}\n" "#endif\n" @@ -1207,7 +1211,7 @@ "#endif\n" "\n" "#ifdef USEFOG\n" -" color.rgb = FogVertex(color.rgb);\n" +" color.rgb = FogVertex(color);\n" "#endif\n" "\n" " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n" diff --git a/shader_hlsl.h b/shader_hlsl.h index 74a02eef..19bf6b82 100644 --- a/shader_hlsl.h +++ b/shader_hlsl.h @@ -472,20 +472,24 @@ "#ifdef FRAGMENT_SHADER\n" "\n" "#ifdef USEFOG\n" -"float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n" +"float3 FogVertex(float4 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n" "{\n" " float fogfrac;\n" +" float3 fc = Fogcolor;\n" +"#ifdef USEFOGALPHAHACK\n" +" fc *= surfacecolor.a;\n" +"#endif\n" "#ifdef USEFOGHEIGHTTEXTURE\n" " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n" " fogfrac = fogheightpixel.a;\n" -" return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n" +" return lerp(fogheightpixel.rgb * fc, surfacecolor.rgb, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n" "#else\n" "# ifdef USEFOGOUTSIDE\n" " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n" "# else\n" " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n" "# endif\n" -" return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n" +" return lerp(fc, surfacecolor.rgb, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n" "#endif\n" "}\n" "#endif\n" @@ -1438,7 +1442,7 @@ "#endif\n" "\n" "#ifdef USEFOG\n" -" color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n" +" color.rgb = FogVertex(color, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n" "#endif\n" "\n" " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"