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:
parent
3df3df9964
commit
c48841cfeb
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()) ) &&
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user