From db99537a6b67f2942c08680787a7215844770f87 Mon Sep 17 00:00:00 2001 From: Sryder13 Date: Sat, 9 Sep 2017 00:41:11 +0100 Subject: [PATCH] Various Transparent Texture Fixes Draw Textures and Flats that have holes in them like a solid polygon so they use the depth buffer and don't need to be sorted Disable all linear filtering on textures and flats that have holes in them, the linear filtering introduces translucency into the textures where the edges are. Leaving them with either a black border, or causing pixels behind the slightly translucent areas to not be drawn. Doesn't apply to sprites and the HUD as they are always already sorted properly. Make the Alpha Testing more strict on non-translucent blend modes. This makes it so any transparency below 0.5 is discarded instead. Would make anything that is blended and has holes in it look slightly better, only the HUD and MD2s where the texture has holes are effected currently. Set TF_TRANSPARENT on flat texture flags when there are holes in the texture. Minor fix to make sure MD2s always set the right blend mode --- src/hardware/hw_main.c | 30 +++++------------ src/hardware/r_opengl/r_opengl.c | 57 ++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index f38e67ce..97178912 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1072,7 +1072,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts of the wall that can't be seen */ - GLTexture_t * glTex; float realtop, realbot, top, bot; float pegt, pegb, pegmul; @@ -1238,11 +1237,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - glTex = HWR_GetTexture(texnum); + //glTex = HWR_GetTexture(texnum); if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); - else if (glTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); @@ -1298,11 +1295,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, wallVerts[0].y = wallVerts[1].y = bot; #endif - glTex = HWR_GetTexture(texnum); + //glTex = HWR_GetTexture(texnum); if (cutflag & FF_TRANSLUCENT) HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); - else if (glTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Environment, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); } @@ -2033,15 +2028,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } #endif - if (grTex->mipmap.flags & TF_TRANSPARENT) - blendmode = PF_Translucent; - if (gr_frontsector->numlights) { if (!(blendmode & PF_Masked)) HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT); else + { HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); + } } else if (!(blendmode & PF_Masked)) HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); @@ -2338,15 +2332,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT) + if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } - else if (grTex->mipmap.flags & TF_TRANSPARENT) - { - blendmode = PF_Environment; - } if (gr_frontsector->numlights) HWR_SplitWall(gr_frontsector, wallVerts, texnum, &Surf, rover->flags); @@ -2461,15 +2451,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT) + if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { blendmode = PF_Translucent; Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; } - else if (grTex->mipmap.flags & TF_TRANSPARENT) - { - blendmode = PF_Environment; - } if (gr_backsector->numlights) HWR_SplitWall(gr_backsector, wallVerts, texnum, &Surf, rover->flags); @@ -3575,7 +3561,7 @@ static void HWR_Subsector(size_t num) alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT) // SoM: Flags are more efficient + else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) // SoM: Flags are more efficient { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING @@ -3638,7 +3624,7 @@ static void HWR_Subsector(size_t num) alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT) + else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) { light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index e6ff83e8..80df8afb 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1056,30 +1056,48 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) switch (PolyFlags & PF_Blending) { case PF_Translucent & PF_Blending: pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; case PF_Masked & PF_Blending: // Hurdler: does that mean lighting is only made by alpha src? // it sounds ok, but not for polygonsmooth pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_GREATER, 0.5f); +#endif break; case PF_Additive & PF_Blending: #ifdef ATI_RAGE_PRO_COMPATIBILITY pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency #else pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest +#endif +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); #endif break; case PF_Environment & PF_Blending: pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; case PF_Substractive & PF_Blending: // good for shadow // not realy but what else ? pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_NOTEQUAL, 0.0f); +#endif break; default : // must be 0, otherwise it's an error // No blending pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending +#ifndef KOS_GL_COMPATIBILITY + pglAlphaFunc(GL_GREATER, 0.5f); +#endif break; } } @@ -1339,6 +1357,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) tex[w*j+i].s.green = 0; tex[w*j+i].s.blue = 0; tex[w*j+i].s.alpha = 0; + pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it } else { @@ -1409,8 +1428,22 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) tex_downloaded = pTexInfo->downloaded; pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues + if (pTexInfo->flags & TF_TRANSPARENT) + { +#ifdef KOS_GL_COMPATIBILITY + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NONE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NONE); +#else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +#endif + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + } #ifdef KOS_GL_COMPATIBILITY pglTexImage2D(GL_TEXTURE_2D, 0, GL_ARGB4444, w, h, 0, GL_ARGB4444, GL_UNSIGNED_BYTE, ptex); @@ -1865,12 +1898,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration ambient[1] = 0.75f; if (ambient[2] > 0.75f) ambient[2] = 0.75f; - - if (color[3] < 255) - { - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - pglDepthMask(GL_FALSE); - } } pglEnable(GL_CULL_FACE); @@ -1897,10 +1924,12 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); #endif + if (color[3] < 255) + SetBlend(PF_Translucent|PF_Modulated|PF_Clip); + else + SetBlend(PF_Masked|PF_Modulated|PF_Occlude|PF_Clip); } - DrawPolygon(NULL, NULL, 0, PF_Masked|PF_Modulated|PF_Occlude|PF_Clip); - pglPushMatrix(); // should be the same as glLoadIdentity //Hurdler: now it seems to work pglTranslatef(pos->x, pos->z, pos->y); @@ -1908,14 +1937,6 @@ static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration scaley = -scaley; pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f); - //pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency - - // Remove depth mask when the model is transparent so it doesn't cut thorugh sprites // SRB2CBTODO: For all stuff too?! - if (color && color[3] < 255) - { - pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency - pglDepthMask(GL_FALSE); - } val = *gl_cmd_buffer++;