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
This commit is contained in:
Sryder13 2017-09-09 00:41:11 +01:00
parent 6877930ed9
commit db99537a6b
2 changed files with 47 additions and 40 deletions

View file

@ -1072,7 +1072,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
/* SoM: split up and light walls according to the /* SoM: split up and light walls according to the
lightlist. This may also include leaving out parts lightlist. This may also include leaving out parts
of the wall that can't be seen */ of the wall that can't be seen */
GLTexture_t * glTex;
float realtop, realbot, top, bot; float realtop, realbot, top, bot;
float pegt, pegb, pegmul; 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; wallVerts[0].y = wallVerts[1].y = bot;
#endif #endif
glTex = HWR_GetTexture(texnum); //glTex = HWR_GetTexture(texnum);
if (cutflag & FF_TRANSLUCENT) if (cutflag & FF_TRANSLUCENT)
HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); 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 else
HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); 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; wallVerts[0].y = wallVerts[1].y = bot;
#endif #endif
glTex = HWR_GetTexture(texnum); //glTex = HWR_GetTexture(texnum);
if (cutflag & FF_TRANSLUCENT) if (cutflag & FF_TRANSLUCENT)
HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); 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 else
HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap);
} }
@ -2033,15 +2028,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
} }
#endif #endif
if (grTex->mipmap.flags & TF_TRANSPARENT)
blendmode = PF_Translucent;
if (gr_frontsector->numlights) if (gr_frontsector->numlights)
{ {
if (!(blendmode & PF_Masked)) if (!(blendmode & PF_Masked))
HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT); HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT);
else else
{
HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS);
}
} }
else if (!(blendmode & PF_Masked)) else if (!(blendmode & PF_Masked))
HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); 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; FBITFIELD blendmode = PF_Masked;
if (rover->flags & FF_TRANSLUCENT) if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256)
{ {
blendmode = PF_Translucent; blendmode = PF_Translucent;
Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; 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) if (gr_frontsector->numlights)
HWR_SplitWall(gr_frontsector, wallVerts, texnum, &Surf, rover->flags); 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; FBITFIELD blendmode = PF_Masked;
if (rover->flags & FF_TRANSLUCENT) if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256)
{ {
blendmode = PF_Translucent; blendmode = PF_Translucent;
Surf.FlatColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; 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) if (gr_backsector->numlights)
HWR_SplitWall(gr_backsector, wallVerts, texnum, &Surf, rover->flags); 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, alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture,
true, rover->master->frontsector->extra_colormap); 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); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
#ifndef SORTING #ifndef SORTING
@ -3638,7 +3624,7 @@ static void HWR_Subsector(size_t num)
alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture, alpha, rover->master->frontsector, PF_Translucent|PF_NoTexture,
true, rover->master->frontsector->extra_colormap); 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); light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
#ifndef SORTING #ifndef SORTING

View file

@ -1056,30 +1056,48 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
switch (PolyFlags & PF_Blending) { switch (PolyFlags & PF_Blending) {
case PF_Translucent & PF_Blending: case PF_Translucent & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
#ifndef KOS_GL_COMPATIBILITY
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
#endif
break; break;
case PF_Masked & PF_Blending: case PF_Masked & PF_Blending:
// Hurdler: does that mean lighting is only made by alpha src? // Hurdler: does that mean lighting is only made by alpha src?
// it sounds ok, but not for polygonsmooth // it sounds ok, but not for polygonsmooth
pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture
#ifndef KOS_GL_COMPATIBILITY
pglAlphaFunc(GL_GREATER, 0.5f);
#endif
break; break;
case PF_Additive & PF_Blending: case PF_Additive & PF_Blending:
#ifdef ATI_RAGE_PRO_COMPATIBILITY #ifdef ATI_RAGE_PRO_COMPATIBILITY
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
#else #else
pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
#endif
#ifndef KOS_GL_COMPATIBILITY
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
#endif #endif
break; break;
case PF_Environment & PF_Blending: case PF_Environment & PF_Blending:
pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
#ifndef KOS_GL_COMPATIBILITY
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
#endif
break; break;
case PF_Substractive & PF_Blending: case PF_Substractive & PF_Blending:
// good for shadow // good for shadow
// not realy but what else ? // not realy but what else ?
pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
#ifndef KOS_GL_COMPATIBILITY
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
#endif
break; break;
default : // must be 0, otherwise it's an error default : // must be 0, otherwise it's an error
// No blending // No blending
pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending
#ifndef KOS_GL_COMPATIBILITY
pglAlphaFunc(GL_GREATER, 0.5f);
#endif
break; break;
} }
} }
@ -1339,6 +1357,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
tex[w*j+i].s.green = 0; tex[w*j+i].s.green = 0;
tex[w*j+i].s.blue = 0; tex[w*j+i].s.blue = 0;
tex[w*j+i].s.alpha = 0; tex[w*j+i].s.alpha = 0;
pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it
} }
else else
{ {
@ -1409,8 +1428,22 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
tex_downloaded = pTexInfo->downloaded; tex_downloaded = pTexInfo->downloaded;
pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); 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 #ifdef KOS_GL_COMPATIBILITY
pglTexImage2D(GL_TEXTURE_2D, 0, GL_ARGB4444, w, h, 0, GL_ARGB4444, GL_UNSIGNED_BYTE, ptex); 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; ambient[1] = 0.75f;
if (ambient[2] > 0.75f) if (ambient[2] > 0.75f)
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); 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_AMBIENT, ambient);
pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
#endif #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 pglPushMatrix(); // should be the same as glLoadIdentity
//Hurdler: now it seems to work //Hurdler: now it seems to work
pglTranslatef(pos->x, pos->z, pos->y); 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; scaley = -scaley;
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
pglRotatef(pos->anglex, -1.0f, 0.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++; val = *gl_cmd_buffer++;