Change shaded blend mode use srcalpha and destalpha.

Fix blending error in add/sub/revsub
This commit is contained in:
Magnus Norddahl 2016-11-21 03:49:55 +01:00
parent 144c7f4139
commit 2ba2dc7611
6 changed files with 68 additions and 69 deletions

View file

@ -107,18 +107,27 @@ SSAVec4i DrawerCodegen::blend_copy(SSAVec4i fg)
SSAVec4i DrawerCodegen::blend_add(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha) SSAVec4i DrawerCodegen::blend_add(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha)
{ {
SSAInt alpha = fg[3];
alpha = alpha + (alpha >> 7); // 255 -> 256
srcalpha = (alpha * srcalpha + 128) >> 8;
SSAVec4i color = (fg * srcalpha + bg * destalpha) / 256; SSAVec4i color = (fg * srcalpha + bg * destalpha) / 256;
return color.insert(3, 255); return color.insert(3, 255);
} }
SSAVec4i DrawerCodegen::blend_sub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha) SSAVec4i DrawerCodegen::blend_sub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha)
{ {
SSAInt alpha = fg[3];
alpha = alpha + (alpha >> 7); // 255 -> 256
srcalpha = (alpha * srcalpha + 128) >> 8;
SSAVec4i color = (bg * destalpha - fg * srcalpha) / 256; SSAVec4i color = (bg * destalpha - fg * srcalpha) / 256;
return color.insert(3, 255); return color.insert(3, 255);
} }
SSAVec4i DrawerCodegen::blend_revsub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha) SSAVec4i DrawerCodegen::blend_revsub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha)
{ {
SSAInt alpha = fg[3];
alpha = alpha + (alpha >> 7); // 255 -> 256
srcalpha = (alpha * srcalpha + 128) >> 8;
SSAVec4i color = (fg * srcalpha - bg * destalpha) / 256; SSAVec4i color = (fg * srcalpha - bg * destalpha) / 256;
return color.insert(3, 255); return color.insert(3, 255);
} }
@ -126,7 +135,7 @@ SSAVec4i DrawerCodegen::blend_revsub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha,
SSAVec4i DrawerCodegen::blend_alpha_blend(SSAVec4i fg, SSAVec4i bg) SSAVec4i DrawerCodegen::blend_alpha_blend(SSAVec4i fg, SSAVec4i bg)
{ {
SSAInt alpha = fg[3]; SSAInt alpha = fg[3];
alpha = alpha + (alpha >> 7); // // 255 -> 256 alpha = alpha + (alpha >> 7); // 255 -> 256
SSAInt inv_alpha = 256 - alpha; SSAInt inv_alpha = 256 - alpha;
SSAVec4i color = (fg * alpha + bg * inv_alpha) / 256; SSAVec4i color = (fg * alpha + bg * inv_alpha) / 256;
return color.insert(3, 255); return color.insert(3, 255);
@ -139,3 +148,15 @@ SSAInt DrawerCodegen::calc_blend_bgalpha(SSAVec4i fg, SSAInt destalpha)
SSAInt inv_alpha = 256 - alpha; SSAInt inv_alpha = 256 - alpha;
return (destalpha * alpha + 256 * inv_alpha + 128) >> 8; return (destalpha * alpha + 256 * inv_alpha + 128) >> 8;
} }
SSAVec4i DrawerCodegen::blend_stencil(SSAVec4i stencilcolor, SSAInt fgalpha, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha)
{
fgalpha = fgalpha + (fgalpha >> 7); // 255 -> 256
SSAInt inv_fgalpha = 256 - fgalpha;
srcalpha = (fgalpha * srcalpha + 128) >> 8;
destalpha = (destalpha * fgalpha + 256 * inv_fgalpha + 128) >> 8;
SSAVec4i color = (stencilcolor * srcalpha + bg * destalpha) / 256;
return color.insert(3, 255);
}

View file

@ -85,6 +85,7 @@ public:
SSAVec4i blend_sub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha); SSAVec4i blend_sub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha);
SSAVec4i blend_revsub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha); SSAVec4i blend_revsub(SSAVec4i fg, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha);
SSAVec4i blend_alpha_blend(SSAVec4i fg, SSAVec4i bg); SSAVec4i blend_alpha_blend(SSAVec4i fg, SSAVec4i bg);
SSAVec4i blend_stencil(SSAVec4i color, SSAInt fgalpha, SSAVec4i bg, SSAInt srcalpha, SSAInt destalpha);
// Calculates the final alpha values to be used when combined with the source texture alpha channel // Calculates the final alpha values to be used when combined with the source texture alpha channel
SSAInt calc_blend_bgalpha(SSAVec4i fg, SSAInt destalpha); SSAInt calc_blend_bgalpha(SSAVec4i fg, SSAInt destalpha);

View file

@ -552,7 +552,6 @@ SSAVec4i DrawTriangleCodegen::ProcessPixel32(SSAVec4i bg, SSAInt *varying)
SSAInt uvoffset = upos * textureHeight + vpos; SSAInt uvoffset = upos * textureHeight + vpos;
SSAVec4i fg; SSAVec4i fg;
SSAInt alpha, inv_alpha;
SSAVec4i output; SSAVec4i output;
switch (blendmode) switch (blendmode)
@ -584,10 +583,7 @@ SSAVec4i DrawTriangleCodegen::ProcessPixel32(SSAVec4i bg, SSAInt *varying)
break; break;
case TriBlendMode::Shaded: case TriBlendMode::Shaded:
fg = Sample32(uvoffset); fg = Sample32(uvoffset);
alpha = fg[0]; output = blend_stencil(shade_bgra_simple(SSAVec4i::unpack(color), currentlight), fg[3], bg, srcalpha, destalpha);
alpha = alpha + (alpha >> 7); // 255 -> 256
inv_alpha = 256 - alpha;
output = blend_add(shade_bgra_simple(SSAVec4i::unpack(color), currentlight), bg, alpha, inv_alpha);
break; break;
case TriBlendMode::TranslateCopy: case TriBlendMode::TranslateCopy:
fg = TranslateSample32(uvoffset); fg = TranslateSample32(uvoffset);
@ -667,10 +663,7 @@ SSAInt DrawTriangleCodegen::ProcessPixel8(SSAInt bg, SSAInt *varying)
output = ToPal8(blend_revsub(fg, ToBgra(bg), srcalpha, calc_blend_bgalpha(fg, destalpha))); output = ToPal8(blend_revsub(fg, ToBgra(bg), srcalpha, calc_blend_bgalpha(fg, destalpha)));
break; break;
case TriBlendMode::Shaded: case TriBlendMode::Shaded:
alpha = Sample8(uvoffset); output = ToPal8(blend_stencil(ToBgra(Shade8(color)), Sample8(uvoffset), ToBgra(bg), srcalpha, destalpha));
alpha = alpha + (alpha >> 7); // 255 -> 256
inv_alpha = 256 - alpha;
output = ToPal8(blend_add(ToBgra(Shade8(color)), ToBgra(bg), alpha, inv_alpha));
break; break;
case TriBlendMode::TranslateCopy: case TriBlendMode::TranslateCopy:
output = Shade8(TranslateSample8(uvoffset)); output = Shade8(TranslateSample8(uvoffset));

View file

@ -281,7 +281,7 @@ enum class TriBlendMode
Add, // blend_add(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) Add, // blend_add(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha))
Sub, // blend_sub(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) Sub, // blend_sub(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha))
RevSub, // blend_revsub(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) RevSub, // blend_revsub(shade(fg), bg, srcalpha, calc_blend_bgalpha(fg, destalpha))
Shaded, // blend_add(color, bg, fg.a, 1 - fg.a) Shaded, // blend_stencil(shade(color), fg, bg, srcalpha, calc_blend_bgalpha(fg, destalpha))
TranslateCopy, // blend_copy(shade(translate(fg))) TranslateCopy, // blend_copy(shade(translate(fg)))
TranslateAlphaBlend, // blend_alpha_blend(shade(translate(fg)), bg) TranslateAlphaBlend, // blend_alpha_blend(shade(translate(fg)), bg)
TranslateAdd, // blend_add(shade(translate(fg)), bg, srcalpha, calc_blend_bgalpha(fg, destalpha)) TranslateAdd, // blend_add(shade(translate(fg)), bg, srcalpha, calc_blend_bgalpha(fg, destalpha))

View file

@ -128,30 +128,31 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, DBaseDecal *decal, co
bool fullbrightSprite = (decal->RenderFlags & RF_FULLBRIGHT) == RF_FULLBRIGHT; bool fullbrightSprite = (decal->RenderFlags & RF_FULLBRIGHT) == RF_FULLBRIGHT;
TriUniforms uniforms; PolyDrawArgs args;
args.uniforms.flags = 0;
if (fullbrightSprite || fixedlightlev >= 0 || fixedcolormap) if (fullbrightSprite || fixedlightlev >= 0 || fixedcolormap)
{ {
uniforms.light = 256; args.uniforms.light = 256;
uniforms.flags = TriUniforms::fixed_light; args.uniforms.flags |= TriUniforms::fixed_light;
} }
else else
{ {
uniforms.light = (uint32_t)((front->lightlevel + actualextralight) / 255.0f * 256.0f); args.uniforms.light = (uint32_t)((front->lightlevel + actualextralight) / 255.0f * 256.0f);
uniforms.flags = 0;
} }
uniforms.subsectorDepth = subsectorDepth; args.uniforms.subsectorDepth = subsectorDepth;
if (r_swtruecolor) if (r_swtruecolor)
{ {
uniforms.color = 0xff000000 | decal->AlphaColor; args.uniforms.color = 0xff000000 | decal->AlphaColor;
} }
else else
{ {
uniforms.color = ((uint32_t)decal->AlphaColor) >> 24; args.uniforms.color = ((uint32_t)decal->AlphaColor) >> 24;
} }
PolyDrawArgs args; args.uniforms.srcalpha = 256;
args.uniforms = uniforms; args.uniforms.destalpha = 0;
args.objectToClip = &worldToClip; args.objectToClip = &worldToClip;
args.vinput = vertices; args.vinput = vertices;
args.vcount = 4; args.vcount = 4;

View file

@ -116,21 +116,19 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, AActor *thing, subse
bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)); bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT));
TriUniforms uniforms; PolyDrawArgs args;
args.uniforms.flags = 0;
if (fullbrightSprite || fixedlightlev >= 0 || fixedcolormap) if (fullbrightSprite || fixedlightlev >= 0 || fixedcolormap)
{ {
uniforms.light = 256; args.uniforms.light = 256;
uniforms.flags = TriUniforms::fixed_light; args.uniforms.flags |= TriUniforms::fixed_light;
} }
else else
{ {
uniforms.light = (uint32_t)((thing->Sector->lightlevel + actualextralight) / 255.0f * 256.0f); args.uniforms.light = (uint32_t)((thing->Sector->lightlevel + actualextralight) / 255.0f * 256.0f);
uniforms.flags = 0;
} }
uniforms.subsectorDepth = subsectorDepth; args.uniforms.subsectorDepth = subsectorDepth;
PolyDrawArgs args;
args.uniforms = uniforms;
args.objectToClip = &worldToClip; args.objectToClip = &worldToClip;
args.vinput = vertices; args.vinput = vertices;
args.vcount = 4; args.vcount = 4;
@ -141,106 +139,91 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, AActor *thing, subse
args.SetTexture(tex, thing->Translation); args.SetTexture(tex, thing->Translation);
args.SetColormap(sub->sector->ColorMap); args.SetColormap(sub->sector->ColorMap);
TriBlendMode blendmode;
if (thing->RenderStyle == LegacyRenderStyles[STYLE_Normal] || if (thing->RenderStyle == LegacyRenderStyles[STYLE_Normal] ||
(r_drawfuzz == 0 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) (r_drawfuzz == 0 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy]))
{ {
args.uniforms.destalpha = 0; args.uniforms.destalpha = 0;
args.uniforms.srcalpha = 256; args.uniforms.srcalpha = 256;
(args.translation) ? blendmode = args.translation ? TriBlendMode::TranslateAdd : TriBlendMode::Add;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::TranslateAdd) :
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Add);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Add]) else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Add])
{ {
args.uniforms.destalpha = (uint32_t)(1.0 * 256); args.uniforms.destalpha = (uint32_t)(1.0 * 256);
args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256); args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256);
(args.translation) ? blendmode = args.translation ? TriBlendMode::TranslateAdd : TriBlendMode::Add;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::TranslateAdd) :
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Add);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Subtract]) else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Subtract])
{ {
args.uniforms.destalpha = (uint32_t)(1.0 * 256); args.uniforms.destalpha = (uint32_t)(1.0 * 256);
args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256); args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256);
(args.translation) ? blendmode = args.translation ? TriBlendMode::TranslateSub : TriBlendMode::Sub;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::TranslateSub) :
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Sub);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_SoulTrans]) else if (thing->RenderStyle == LegacyRenderStyles[STYLE_SoulTrans])
{ {
args.uniforms.destalpha = (uint32_t)(256 - transsouls * 256); args.uniforms.destalpha = (uint32_t)(256 - transsouls * 256);
args.uniforms.srcalpha = (uint32_t)(transsouls * 256); args.uniforms.srcalpha = (uint32_t)(transsouls * 256);
(args.translation) ? blendmode = args.translation ? TriBlendMode::TranslateAdd : TriBlendMode::Add;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::TranslateAdd) :
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Add);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Fuzzy] || else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Fuzzy] ||
(r_drawfuzz == 2 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) (r_drawfuzz == 2 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy]))
{ // NYI - Fuzzy - for now, just a copy of "Shadow" { // NYI - Fuzzy - for now, just a copy of "Shadow"
args.uniforms.destalpha = 160; args.uniforms.destalpha = 160;
args.uniforms.srcalpha = 0; args.uniforms.srcalpha = 0;
(args.translation) ? blendmode = args.translation ? TriBlendMode::TranslateAdd : TriBlendMode::Add;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::TranslateAdd) :
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Add);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Shadow] || else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Shadow] ||
(r_drawfuzz == 1 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy])) (r_drawfuzz == 1 && thing->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy]))
{ {
args.uniforms.destalpha = 160; args.uniforms.destalpha = 160;
args.uniforms.srcalpha = 0; args.uniforms.srcalpha = 0;
(args.translation) ? blendmode = args.translation ? TriBlendMode::TranslateAdd : TriBlendMode::Add;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::TranslateAdd) :
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Add);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_TranslucentStencil]) else if (thing->RenderStyle == LegacyRenderStyles[STYLE_TranslucentStencil])
{ {
// NYI
args.uniforms.destalpha = (uint32_t)(256 - thing->Alpha * 256); args.uniforms.destalpha = (uint32_t)(256 - thing->Alpha * 256);
args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256); args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256);
args.uniforms.color = 0xff000000 | thing->fillcolor; args.uniforms.color = 0xff000000 | thing->fillcolor;
(args.translation) ? blendmode = TriBlendMode::Shaded;
PolyTriangleDrawer::draw(args, TriDrawVariant::FillSubsector, TriBlendMode::TranslateAdd) :
PolyTriangleDrawer::draw(args, TriDrawVariant::FillSubsector, TriBlendMode::Add);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_AddStencil]) else if (thing->RenderStyle == LegacyRenderStyles[STYLE_AddStencil])
{ {
// NYI
args.uniforms.destalpha = 256; args.uniforms.destalpha = 256;
args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256); args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256) * 2; // Don't know this needs to be multiplied by two..
args.uniforms.color = 0xff000000 | thing->fillcolor; args.uniforms.color = 0xff000000 | thing->fillcolor;
(args.translation) ? blendmode = TriBlendMode::Shaded;
PolyTriangleDrawer::draw(args, TriDrawVariant::FillSubsector, TriBlendMode::TranslateAdd) :
PolyTriangleDrawer::draw(args, TriDrawVariant::FillSubsector, TriBlendMode::Add);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Shaded]) else if (thing->RenderStyle == LegacyRenderStyles[STYLE_Shaded])
{ {
args.uniforms.destalpha = 256;
args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256); args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256);
args.SetTexture(tex, false); args.uniforms.destalpha = 256 - args.uniforms.srcalpha;
args.uniforms.color = 0; args.uniforms.color = 0;
uniforms.flags |= TriUniforms::simple_shade; blendmode = TriBlendMode::Shaded;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Shaded);
} }
else if (thing->RenderStyle == LegacyRenderStyles[STYLE_AddShaded]) else if (thing->RenderStyle == LegacyRenderStyles[STYLE_AddShaded])
{ // NYI? {
args.uniforms.destalpha = 256; args.uniforms.destalpha = 256;
args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256); args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256);
args.SetTexture(tex, false);
args.uniforms.color = 0; args.uniforms.color = 0;
uniforms.flags |= TriUniforms::simple_shade; blendmode = TriBlendMode::Shaded;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Shaded);
} }
else else
{ {
args.uniforms.destalpha = (uint32_t)(256 - thing->Alpha * 256); args.uniforms.destalpha = (uint32_t)(256 - thing->Alpha * 256);
args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256); args.uniforms.srcalpha = (uint32_t)(thing->Alpha * 256);
(args.translation) ? blendmode = args.translation ? TriBlendMode::TranslateAdd : TriBlendMode::Add;
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::TranslateAdd) :
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Add);
} }
if (!r_swtruecolor)
{
uint32_t r = (args.uniforms.color >> 16) & 0xff;
uint32_t g = (args.uniforms.color >> 8) & 0xff;
uint32_t b = args.uniforms.color & 0xff;
args.uniforms.color = RGB32k.RGB[r >> 3][g >> 3][b >> 3];
}
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, blendmode);
} }
bool RenderPolySprite::IsThingCulled(AActor *thing) bool RenderPolySprite::IsThingCulled(AActor *thing)