1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Implement dual source blending.

Fixes Donkey Kong 64: Gate textures change from a distance. #585
Fixes Pokemon Stadium wrong transparency in warning sign #728
This commit is contained in:
S2S 2020-04-28 17:24:26 +02:00 committed by Sergey Lipskiy
parent 3df3df9964
commit c48841cfeb
14 changed files with 277 additions and 107 deletions

View File

@ -17,6 +17,7 @@ bool Context::FramebufferFetch = false;
bool Context::TextureBarrier = false;
bool Context::EglImage = false;
bool Context::EglImageFramebuffer = false;
bool Context::DualSourceBlending = false;
Context::Context() {}
@ -41,7 +42,8 @@ void Context::init()
FramebufferFetch = m_impl->isSupported(SpecialFeatures::FramebufferFetch);
TextureBarrier = m_impl->isSupported(SpecialFeatures::TextureBarrier);
EglImage = m_impl->isSupported(SpecialFeatures::EglImage);
EglImageFramebuffer = m_impl->isSupported(SpecialFeatures::EglImageFramebuffer);
EglImageFramebuffer = m_impl->isSupported(SpecialFeatures::EglImageFramebuffer);
DualSourceBlending = m_impl->isSupported(SpecialFeatures::DualSourceBlending);
}
void Context::destroy()

View File

@ -27,7 +27,8 @@ namespace graphics {
FramebufferFetch,
TextureBarrier,
EglImage,
EglImageFramebuffer
EglImageFramebuffer,
DualSourceBlending
};
enum class ClampMode {
@ -302,6 +303,7 @@ namespace graphics {
static bool TextureBarrier;
static bool EglImage;
static bool EglImageFramebuffer;
static bool DualSourceBlending;
private:
std::unique_ptr<ContextImpl> m_impl;

View File

@ -514,6 +514,8 @@ public:
ss << "#version " << Utils::to_string(_glinfo.majorVersion) << Utils::to_string(_glinfo.minorVersion) << "0 es " << std::endl;
if (_glinfo.noPerspective)
ss << "#extension GL_NV_shader_noperspective_interpolation : enable" << std::endl;
if (_glinfo.dual_source_blending)
ss << "#extension GL_EXT_blend_func_extended : enable" << std::endl;
if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast) {
if (_glinfo.imageTextures && _glinfo.fragment_interlockNV) {
ss << "#extension GL_NV_fragment_shader_interlock : enable" << std::endl
@ -560,21 +562,40 @@ public:
class ShaderBlender1 : public ShaderPart
{
public:
ShaderBlender1()
ShaderBlender1(const opengl::GLInfo & _glinfo)
{
#if 1
m_part =
" #define MUXA(pos) dot(muxA, STVEC(pos)) \n"
" #define MUXB(pos) dot(muxB, STVEC(pos)) \n"
" #define MUXPM(pos) muxPM*(STVEC(pos)) \n"
" muxPM[0] = clampedColor; \n"
" if (uForceBlendCycle1 != 0) { \n"
" muxA[0] = clampedColor.a; \n"
" muxB[0] = 1.0 - MUXA(uBlendMux1[1]); \n"
" lowp vec4 blend1 = MUXPM(uBlendMux1[0]) * MUXA(uBlendMux1[1]) + MUXPM(uBlendMux1[2]) * MUXB(uBlendMux1[3]); \n"
" clampedColor.rgb = clamp(blend1.rgb, 0.0, 1.0); \n"
" } else clampedColor.rgb = (MUXPM(uBlendMux1[0])).rgb; \n"
m_part =
" srcColor1 = vec4(0.0); \n"
" dstFactor1 = 0.0; \n"
" muxPM[0] = clampedColor; \n"
" muxA[0] = clampedColor.a; \n"
" muxa = MUXA(uBlendMux1[1]); \n"
" muxB[0] = 1.0 - muxa; \n"
" muxb = MUXB(uBlendMux1[3]); \n"
" muxp = MUXPM(uBlendMux1[0]); \n"
" muxm = MUXPM(uBlendMux1[2]); \n"
" muxaf = MUXF(uBlendMux1[0]); \n"
" muxbf = MUXF(uBlendMux1[2]); \n"
" if (uForceBlendCycle1 != 0) { \n"
" srcColor1 = muxp * muxa + muxm * muxb; \n"
" dstFactor1 = muxaf * muxa + muxbf * muxb; \n"
" srcColor1 = clamp(srcColor1, 0.0, 1.0); \n"
" } else { \n"
" srcColor1 = muxp; \n"
" dstFactor1 = muxaf; \n"
" } \n"
;
if (_glinfo.dual_source_blending) {
m_part +=
" fragColor = srcColor1; \n"
" fragColor1 = vec4(dstFactor1); \n"
;
} else {
m_part +=
" fragColor = vec4(srcColor1.rgb, clampedColor.a); \n"
;
}
#else
// Keep old code for reference
m_part =
@ -593,19 +614,41 @@ public:
class ShaderBlender2 : public ShaderPart
{
public:
ShaderBlender2()
ShaderBlender2(const opengl::GLInfo & _glinfo)
{
#if 1
m_part =
" muxPM[0] = clampedColor; \n"
" muxPM[1] = vec4(0.0); \n"
" if (uForceBlendCycle2 != 0) { \n"
" muxA[0] = clampedColor.a; \n"
" muxB[0] = 1.0 - MUXA(uBlendMux2[1]); \n"
" lowp vec4 blend2 = MUXPM(uBlendMux2[0]) * MUXA(uBlendMux2[1]) + MUXPM(uBlendMux2[2]) * MUXB(uBlendMux2[3]); \n"
" clampedColor.rgb = clamp(blend2.rgb, 0.0, 1.0); \n"
" } else clampedColor.rgb = (MUXPM(uBlendMux2[0])).rgb; \n"
" srcColor2 = vec4(0.0); \n"
" dstFactor2 = 0.0; \n"
" muxPM[0] = srcColor1; \n"
" muxa = MUXA(uBlendMux2[1]); \n"
" muxB[0] = 1.0 - muxa; \n"
" muxb = MUXB(uBlendMux2[3]); \n"
" muxp = MUXPM(uBlendMux2[0]); \n"
" muxm = MUXPM(uBlendMux2[2]); \n"
" muxF[0] = dstFactor1; \n"
" muxaf = MUXF(uBlendMux2[0]); \n"
" muxbf = MUXF(uBlendMux2[2]); \n"
" if (uForceBlendCycle2 != 0) { \n"
" srcColor2 = muxp * muxa + muxm * muxb; \n"
" dstFactor2 = muxaf * muxa + muxbf * muxb; \n"
" srcColor2 = clamp(srcColor2, 0.0, 1.0); \n"
" } else { \n"
" srcColor2 = muxp; \n"
" dstFactor2 = muxaf; \n"
" } \n"
;
if (_glinfo.dual_source_blending) {
m_part +=
" fragColor = srcColor2; \n"
" fragColor1 = vec4(dstFactor2); \n"
;
} else {
m_part +=
" fragColor = vec4(srcColor2.rgb, clampedColor.a); \n"
;
}
#else
// Keep old code for reference
m_part =
@ -622,6 +665,24 @@ public:
}
};
class ShaderBlenderAlpha : public ShaderPart
{
public:
ShaderBlenderAlpha(const opengl::GLInfo & _glinfo)
{
if (_glinfo.dual_source_blending)
m_part +=
"lowp float cvg = clampedColor.a; \n"
"lowp vec4 srcAlpha = vec4(cvg, cvg, 1.0, 0.0); \n"
"lowp vec4 dstFactorAlpha = vec4(1.0, 1.0, 0.0, 1.0); \n"
"if (uForceBlendAlpha == 0) \n"
" dstFactorAlpha[0] = 0.0; \n"
"fragColor.a = srcAlpha[uCvgDest]; \n"
"fragColor1.a = dstFactorAlpha[uCvgDest]; \n"
;
}
};
class ShaderLegacyBlender : public ShaderPart
{
public:
@ -871,7 +932,9 @@ public:
"highp vec2 texCoord1; \n"
"highp vec2 tcData0[5]; \n"
"highp vec2 tcData1[5]; \n"
;
"uniform lowp int uCvgDest; \n"
"uniform lowp int uForceBlendAlpha; \n"
;
if (config.generalEmulation.enableLegacyBlending != 0) {
m_part +=
@ -924,15 +987,21 @@ public:
"IN lowp float vNumLights; \n"
;
if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) {
if (_glinfo.dual_source_blending) {
m_part +=
"layout(location = 0) OUT lowp vec4 fragColor; \n"
"layout(location = 1) inout highp vec4 depthZ; \n"
"layout(location = 2) inout highp vec4 depthDeltaZ; \n"
"layout(location = 0, index = 0) OUT lowp vec4 fragColor; \n"
"layout(location = 0, index = 1) OUT lowp vec4 fragColor1; \n"
;
} else {
m_part +=
"OUT lowp vec4 fragColor; \n"
;
}
if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) {
m_part +=
"layout(location = 1) inout highp vec4 depthZ; \n"
"layout(location = 2) inout highp vec4 depthDeltaZ; \n"
;
}
}
@ -964,6 +1033,9 @@ public:
"uniform highp float uPrimDepth; \n"
"uniform mediump vec2 uScreenScale; \n"
"uniform lowp int uScreenSpaceTriangle; \n"
"uniform lowp int uCvgDest; \n"
"uniform lowp int uForceBlendAlpha; \n"
;
if (config.generalEmulation.enableLegacyBlending != 0) {
@ -1006,17 +1078,23 @@ public:
"IN lowp float vNumLights; \n"
;
if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) {
if (_glinfo.dual_source_blending) {
m_part +=
"layout(location = 0) OUT lowp vec4 fragColor; \n"
"layout(location = 1) inout highp vec4 depthZ; \n"
"layout(location = 2) inout highp vec4 depthDeltaZ; \n"
"layout(location = 0, index = 0) OUT lowp vec4 fragColor; \n"
"layout(location = 0, index = 1) OUT lowp vec4 fragColor1; \n"
;
} else {
m_part +=
"OUT lowp vec4 fragColor; \n"
;
;
}
if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) {
m_part +=
"layout(location = 1) inout highp vec4 depthZ; \n"
"layout(location = 2) inout highp vec4 depthDeltaZ; \n"
;
}
}
};
@ -1418,9 +1496,16 @@ public:
{
if (config.generalEmulation.enableLegacyBlending == 0) {
m_part =
" #define MUXA(pos) dot(muxA, STVEC(pos)) \n"
" #define MUXB(pos) dot(muxB, STVEC(pos)) \n"
" #define MUXPM(pos) muxPM*(STVEC(pos)) \n"
" #define MUXF(pos) dot(muxF, STVEC(pos)) \n"
" lowp mat4 muxPM = mat4(vec4(0.0), vec4(0.0), uBlendColor, uFogColor); \n"
" lowp vec4 muxA = vec4(0.0, uFogColor.a, shadeColor.a, 0.0); \n"
" lowp vec4 muxB = vec4(0.0, 1.0, 1.0, 0.0); \n"
" lowp vec4 muxF = vec4(0.0, 1.0, 0.0, 0.0); \n"
" lowp vec4 muxp, muxm, srcColor1, srcColor2; \n"
" lowp float muxa, muxb, dstFactor1, dstFactor2, muxaf, muxbf; \n"
;
}
}
@ -2572,12 +2657,14 @@ CombinerInputs CombinerProgramBuilder::compileCombiner(const CombinerKey & _key,
m_callDither->write(ssShader);
if (config.generalEmulation.enableLegacyBlending == 0) {
if (g_cycleType <= G_CYC_2CYCLE)
if (g_cycleType <= G_CYC_2CYCLE) {
m_blender1->write(ssShader);
if (g_cycleType == G_CYC_2CYCLE)
m_blender2->write(ssShader);
if (g_cycleType == G_CYC_2CYCLE)
m_blender2->write(ssShader);
m_blenderAlpha->write(ssShader);
} else
ssShader << " fragColor = clampedColor;" << std::endl;
ssShader << " fragColor = clampedColor;" << std::endl;
}
else {
ssShader << " fragColor = clampedColor;" << std::endl;
@ -2792,8 +2879,9 @@ GLuint _createVertexShader(ShaderPart * _header, ShaderPart * _body, ShaderPart
}
CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, opengl::CachedUseProgram * _useProgram)
: m_blender1(new ShaderBlender1)
, m_blender2(new ShaderBlender2)
: m_blender1(new ShaderBlender1(_glinfo))
, m_blender2(new ShaderBlender2(_glinfo))
, m_blenderAlpha (new ShaderBlenderAlpha(_glinfo))
, m_legacyBlender(new ShaderLegacyBlender)
, m_clamp(new ShaderClamp)
, m_signExtendColorC(new ShaderSignExtendColorC)

View File

@ -39,6 +39,7 @@ namespace glsl {
typedef std::unique_ptr<ShaderPart> ShaderPartPtr;
ShaderPartPtr m_blender1;
ShaderPartPtr m_blender2;
ShaderPartPtr m_blenderAlpha;
ShaderPartPtr m_legacyBlender;
ShaderPartPtr m_clamp;
ShaderPartPtr m_signExtendColorC;

View File

@ -369,30 +369,33 @@ public:
const int forceBlend2 = gDP.otherMode.forceBlender;
uForceBlendCycle2.set(forceBlend2, _force);
// Modes, which shader blender can't emulate
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
switch (mode) {
case 0x0040:
// Mia Hamm Soccer
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_in * (1-a)
case 0x0050:
// A Bug's Life
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_mem * (1-a)
uForceBlendCycle1.set(0, _force);
uForceBlendCycle2.set(0, _force);
break;
case 0x0150:
// Tony Hawk
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_fog + clr_mem * (1-a_fog)
if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) {
if (!graphics::Context::DualSourceBlending) {
// Modes, which shader blender can't emulate
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
switch (mode) {
case 0x0040:
// Mia Hamm Soccer
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_in * (1-a)
case 0x0050:
// A Bug's Life
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_mem * (1-a)
uForceBlendCycle1.set(0, _force);
uForceBlendCycle2.set(0, _force);
break;
case 0x0150:
// Tony Hawk
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_fog + clr_mem * (1-a_fog)
if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) {
uForceBlendCycle1.set(0, _force);
uForceBlendCycle2.set(0, _force);
}
break;
}
break;
}
}
private:
@ -402,6 +405,24 @@ private:
iUniform uForceBlendCycle2;
};
class UBlendCvg : public UniformGroup
{
public:
UBlendCvg(GLuint _program) {
LocateUniform(uCvgDest);
LocateUniform(uForceBlendAlpha);
}
void update(bool _force) override
{
uCvgDest.set(gDP.otherMode.cvgDest, _force);
uForceBlendAlpha.set(gDP.otherMode.forceBlender, _force);
}
private:
iUniform uCvgDest;
iUniform uForceBlendAlpha;
};
class UDitherMode : public UniformGroup
{
public:
@ -1126,6 +1147,8 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
}
}
_uniforms.emplace_back(new UBlendCvg(_program));
_uniforms.emplace_back(new UDitherMode(_program, _inputs.usesNoise()));
_uniforms.emplace_back(new UScreenScale(_program));

View File

@ -313,8 +313,7 @@ namespace glsl {
"{ \n"
" TEX_FILTER(fragColor, uTex0, vTexCoord0); \n"
;
if (!_glinfo.isGLES2 &&
config.generalEmulation.enableFragmentDepthWrite != 0 &&
if (config.generalEmulation.enableFragmentDepthWrite != 0 &&
config.frameBufferEmulation.N64DepthCompare == Config::dcDisable) {
m_part +=
" gl_FragDepth = uPrimDepth; \n"

View File

@ -156,11 +156,13 @@ void ContextImpl::setScissor(s32 _x, s32 _y, s32 _width, s32 _height)
void ContextImpl::setBlending(graphics::BlendParam _sfactor, graphics::BlendParam _dfactor)
{
m_cachedFunctions->getCachedBlending()->setBlending(_sfactor, _dfactor);
m_cachedFunctions->getCachedBlendingSeparate()->reset();
}
void ContextImpl::setBlendingSeparate(graphics::BlendParam _sfactorcolor, graphics::BlendParam _dfactorcolor, graphics::BlendParam _sfactoralpha, graphics::BlendParam _dfactoralpha)
{
m_cachedFunctions->getCachedBlendingSeparate()->setBlendingSeparate(_sfactorcolor, _dfactorcolor, _sfactoralpha, _dfactoralpha);
m_cachedFunctions->getCachedBlending()->reset();
}
void ContextImpl::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
@ -518,6 +520,8 @@ bool ContextImpl::isSupported(graphics::SpecialFeatures _feature) const
return m_glInfo.eglImage;
case graphics::SpecialFeatures::EglImageFramebuffer:
return m_glInfo.eglImageFramebuffer;
case graphics::SpecialFeatures::DualSourceBlending:
return m_glInfo.dual_source_blending;
}
return false;
}

View File

@ -160,6 +160,8 @@ void GLInfo::init() {
ext_fetch = Utils::isExtensionSupported(*this, "GL_EXT_shader_framebuffer_fetch") && !isGLES2 && (!isGLESX || ext_draw_buffers_indexed) && !imageTexturesInterlock;
eglImage = (Utils::isEGLExtensionSupported("EGL_KHR_image_base") || Utils::isEGLExtensionSupported("EGL_KHR_image"));
dual_source_blending = !(isGLESX) || Utils::isExtensionSupported(*this, "GL_EXT_blend_func_extended");
#ifdef OS_ANDROID
eglImage = eglImage &&
( (isGLES2 && GraphicBufferWrapper::isSupportAvailable()) || (isGLESX && GraphicBufferWrapper::isPublicSupportAvailable()) ) &&

View File

@ -35,6 +35,7 @@ struct GLInfo {
bool ext_fetch = false;
bool eglImage = false;
bool eglImageFramebuffer = false;
bool dual_source_blending = false;
Renderer renderer = Renderer::Other;
void init();

View File

@ -117,6 +117,10 @@ namespace graphics {
BlendParam ONE_MINUS_SRC_ALPHA(GL_ONE_MINUS_SRC_ALPHA);
BlendParam CONSTANT_ALPHA(GL_CONSTANT_ALPHA);
BlendParam ONE_MINUS_CONSTANT_ALPHA(GL_ONE_MINUS_CONSTANT_ALPHA);
BlendParam SRC1_COLOR(GL_SRC1_COLOR);
BlendParam ONE_MINUS_SRC1_COLOR(GL_ONE_MINUS_SRC1_COLOR);
BlendParam SRC1_ALPHA(GL_SRC1_ALPHA);
BlendParam ONE_MINUS_SRC1_ALPHA(GL_ONE_MINUS_SRC1_ALPHA);
}
namespace drawmode {

View File

@ -117,6 +117,10 @@ namespace graphics {
extern BlendParam ONE_MINUS_SRC_ALPHA;
extern BlendParam CONSTANT_ALPHA;
extern BlendParam ONE_MINUS_CONSTANT_ALPHA;
extern BlendParam SRC1_COLOR;
extern BlendParam ONE_MINUS_SRC1_COLOR;
extern BlendParam SRC1_ALPHA;
extern BlendParam ONE_MINUS_SRC1_ALPHA;
}
namespace drawmode {

View File

@ -314,8 +314,7 @@ void GraphicsDrawer::_updateScreenCoordsViewport(const FrameBuffer * _pBuffer) c
gSP.changed |= CHANGED_VIEWPORT;
}
static
void _legacySetBlendMode()
void GraphicsDrawer::_legacyBlending() const
{
const u32 blendmode = gDP.otherMode.l >> 16;
// 0x7000 = CVG_X_ALPHA|ALPHA_CVG_SEL|FORCE_BL
@ -478,48 +477,36 @@ void _legacySetBlendMode()
}
}
bool GraphicsDrawer::_setUnsupportedBlendMode() const
void GraphicsDrawer::_ordinaryBlending() const
{
if (gDP.otherMode.cycleType != G_CYC_2CYCLE)
return false;
// Modes, which shader blender can't emulate
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
switch (mode) {
case 0x0040:
// Mia Hamm Soccer
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_in * (1-a)
case 0x0050:
// A Bug's Life
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_mem * (1-a)
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::SRC_ALPHA, blend::ONE_MINUS_SRC_ALPHA);
return true;
case 0x0150:
// Tony Hawk
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_fog + clr_mem * (1-a_fog)
if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) {
// Set unsupported blend modes
if (gDP.otherMode.cycleType == G_CYC_2CYCLE) {
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
switch (mode) {
case 0x0040:
// Mia Hamm Soccer
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_in * (1-a)
case 0x0050:
// A Bug's Life
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_in + clr_mem * (1-a)
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::SRC_ALPHA, blend::ONE_MINUS_SRC_ALPHA);
return true;
return;
case 0x0150:
// Tony Hawk
// clr_in * a_in + clr_mem * (1-a)
// clr_in * a_fog + clr_mem * (1-a_fog)
if ((config.generalEmulation.hacks & hack_TonyHawk) != 0) {
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::SRC_ALPHA, blend::ONE_MINUS_SRC_ALPHA);
return;
}
break;
}
break;
}
return false;
}
void GraphicsDrawer::_setBlendMode() const
{
if (config.generalEmulation.enableLegacyBlending != 0) {
_legacySetBlendMode();
return;
}
if (_setUnsupportedBlendMode())
return;
if (gDP.otherMode.forceBlender != 0 && gDP.otherMode.cycleType < G_CYC_COPY) {
BlendParam srcFactor = blend::ONE;
@ -535,7 +522,8 @@ void GraphicsDrawer::_setBlendMode() const
return;
}
memFactorSource = 0;
} else if (gDP.otherMode.c2_m2a == 1) {
}
else if (gDP.otherMode.c2_m2a == 1) {
memFactorSource = 1;
}
if (gDP.otherMode.c2_m2a == 0 && gDP.otherMode.c2_m2b == 1) {
@ -552,8 +540,7 @@ void GraphicsDrawer::_setBlendMode() const
return;
}
memFactorSource = 0;
}
else if (gDP.otherMode.c1_m2a == 1) {
} else if (gDP.otherMode.c1_m2a == 1) {
memFactorSource = 1;
}
if (gDP.otherMode.c1_m2a == 0 && gDP.otherMode.c1_m2b == 1) {
@ -641,6 +628,56 @@ void GraphicsDrawer::_setBlendMode() const
}
}
void GraphicsDrawer::_dualSourceBlending() const
{
if (gDP.otherMode.cycleType < G_CYC_COPY) {
BlendParam srcFactor = blend::ONE;
BlendParam dstFactor = blend::SRC1_COLOR;
BlendParam srcFactorAlpha = blend::ONE;
BlendParam dstFactorAlpha = blend::SRC1_ALPHA;
if (gDP.otherMode.forceBlender != 0) {
if (gDP.otherMode.cycleType == G_CYC_2CYCLE) {
if (gDP.otherMode.c2_m2a != 1 && gDP.otherMode.c2_m2b == 1) {
srcFactor = blend::DST_ALPHA;
}
if (gDP.otherMode.c2_m2a == 1 && gDP.otherMode.c2_m2b == 1) {
dstFactor = blend::DST_ALPHA;
}
} else {
if (gDP.otherMode.c1_m2a != 1 && gDP.otherMode.c1_m2b == 1) {
srcFactor = blend::DST_ALPHA;
}
if (gDP.otherMode.c1_m2a == 1 && gDP.otherMode.c2_m2b == 1) {
dstFactor = blend::DST_ALPHA;
}
}
} else if ((config.generalEmulation.hacks & hack_blastCorps) != 0 &&
gSP.texture.on == 0 && currentCombiner()->usesTexture()) { // Blast Corps
srcFactor = blend::ZERO;
dstFactor = blend::ONE;
}
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlendingSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
} else {
gfxContext.enable(enable::BLEND, false);
}
}
void GraphicsDrawer::setBlendMode(bool _forceLegacyBlending) const
{
if (_forceLegacyBlending || config.generalEmulation.enableLegacyBlending != 0) {
_legacyBlending();
return;
}
if (Context::DualSourceBlending) {
_dualSourceBlending();
return;
}
_ordinaryBlending();
}
void GraphicsDrawer::_updateTextures() const
{
//For some reason updating the texture cache on the first frame of LOZ:OOT causes a nullptr Pointer exception...
@ -685,7 +722,7 @@ void GraphicsDrawer::_updateStates(DrawingState _drawingState) const
}
if ((gDP.changed & (CHANGED_RENDERMODE | CHANGED_CYCLETYPE))) {
_setBlendMode();
setBlendMode();
gDP.changed &= ~(CHANGED_RENDERMODE | CHANGED_CYCLETYPE);
}
@ -1053,7 +1090,7 @@ bool texturedRectShadowMap(const GraphicsDrawer::TexturedRectParams &)
pCurrentBuffer->m_pDepthBuffer->activateDepthBufferTexture(pCurrentBuffer);
CombinerInfo::get().setDepthFogCombiner();
// DepthFogCombiner does not support shader blending.
_legacySetBlendMode();
dwnd().getDrawer().setBlendMode(true);
return false;
}
}

View File

@ -158,6 +158,8 @@ public:
void setBackgroundDrawingMode(bool _mode) { m_bBGMode = _mode; }
void setBlendMode(bool _forceLegacyBlending = false) const;
private:
friend class DisplayWindow;
friend TexrectDrawer;
@ -173,8 +175,9 @@ private:
void _setSpecialTexrect() const;
void _setBlendMode() const;
bool _setUnsupportedBlendMode() const;
void _legacyBlending() const;
void _ordinaryBlending() const;
void _dualSourceBlending() const;
void _updateCullFace() const;
void _updateViewport() const;
void _updateScreenCoordsViewport(const FrameBuffer * _pBuffer = nullptr) const;

View File

@ -350,7 +350,7 @@ bool TexrectDrawer::draw()
ValueKeeper<gDPScissor> scissor(gDP.scissor, m_scissor);
DisplayWindow & wnd = dwnd();
GraphicsDrawer & drawer = wnd.getDrawer();
drawer._setBlendMode();
drawer.setBlendMode();
gDP.changed |= CHANGED_RENDERMODE; // Force update of depth compare parameters
drawer._updateDepthCompare();