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
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

View file

@ -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++;