mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +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::TextureBarrier = false;
|
||||||
bool Context::EglImage = false;
|
bool Context::EglImage = false;
|
||||||
bool Context::EglImageFramebuffer = false;
|
bool Context::EglImageFramebuffer = false;
|
||||||
|
bool Context::DualSourceBlending = false;
|
||||||
|
|
||||||
Context::Context() {}
|
Context::Context() {}
|
||||||
|
|
||||||
|
@ -41,7 +42,8 @@ void Context::init()
|
||||||
FramebufferFetch = m_impl->isSupported(SpecialFeatures::FramebufferFetch);
|
FramebufferFetch = m_impl->isSupported(SpecialFeatures::FramebufferFetch);
|
||||||
TextureBarrier = m_impl->isSupported(SpecialFeatures::TextureBarrier);
|
TextureBarrier = m_impl->isSupported(SpecialFeatures::TextureBarrier);
|
||||||
EglImage = m_impl->isSupported(SpecialFeatures::EglImage);
|
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()
|
void Context::destroy()
|
||||||
|
|
|
@ -27,7 +27,8 @@ namespace graphics {
|
||||||
FramebufferFetch,
|
FramebufferFetch,
|
||||||
TextureBarrier,
|
TextureBarrier,
|
||||||
EglImage,
|
EglImage,
|
||||||
EglImageFramebuffer
|
EglImageFramebuffer,
|
||||||
|
DualSourceBlending
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ClampMode {
|
enum class ClampMode {
|
||||||
|
@ -302,6 +303,7 @@ namespace graphics {
|
||||||
static bool TextureBarrier;
|
static bool TextureBarrier;
|
||||||
static bool EglImage;
|
static bool EglImage;
|
||||||
static bool EglImageFramebuffer;
|
static bool EglImageFramebuffer;
|
||||||
|
static bool DualSourceBlending;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ContextImpl> m_impl;
|
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;
|
ss << "#version " << Utils::to_string(_glinfo.majorVersion) << Utils::to_string(_glinfo.minorVersion) << "0 es " << std::endl;
|
||||||
if (_glinfo.noPerspective)
|
if (_glinfo.noPerspective)
|
||||||
ss << "#extension GL_NV_shader_noperspective_interpolation : enable" << std::endl;
|
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 (config.frameBufferEmulation.N64DepthCompare == Config::dcFast) {
|
||||||
if (_glinfo.imageTextures && _glinfo.fragment_interlockNV) {
|
if (_glinfo.imageTextures && _glinfo.fragment_interlockNV) {
|
||||||
ss << "#extension GL_NV_fragment_shader_interlock : enable" << std::endl
|
ss << "#extension GL_NV_fragment_shader_interlock : enable" << std::endl
|
||||||
|
@ -560,21 +562,40 @@ public:
|
||||||
class ShaderBlender1 : public ShaderPart
|
class ShaderBlender1 : public ShaderPart
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShaderBlender1()
|
ShaderBlender1(const opengl::GLInfo & _glinfo)
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
m_part =
|
m_part =
|
||||||
" #define MUXA(pos) dot(muxA, STVEC(pos)) \n"
|
" srcColor1 = vec4(0.0); \n"
|
||||||
" #define MUXB(pos) dot(muxB, STVEC(pos)) \n"
|
" dstFactor1 = 0.0; \n"
|
||||||
" #define MUXPM(pos) muxPM*(STVEC(pos)) \n"
|
" muxPM[0] = clampedColor; \n"
|
||||||
" muxPM[0] = clampedColor; \n"
|
" muxA[0] = clampedColor.a; \n"
|
||||||
" if (uForceBlendCycle1 != 0) { \n"
|
" muxa = MUXA(uBlendMux1[1]); \n"
|
||||||
" muxA[0] = clampedColor.a; \n"
|
" muxB[0] = 1.0 - muxa; \n"
|
||||||
" muxB[0] = 1.0 - MUXA(uBlendMux1[1]); \n"
|
" muxb = MUXB(uBlendMux1[3]); \n"
|
||||||
" lowp vec4 blend1 = MUXPM(uBlendMux1[0]) * MUXA(uBlendMux1[1]) + MUXPM(uBlendMux1[2]) * MUXB(uBlendMux1[3]); \n"
|
" muxp = MUXPM(uBlendMux1[0]); \n"
|
||||||
" clampedColor.rgb = clamp(blend1.rgb, 0.0, 1.0); \n"
|
" muxm = MUXPM(uBlendMux1[2]); \n"
|
||||||
" } else clampedColor.rgb = (MUXPM(uBlendMux1[0])).rgb; \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
|
#else
|
||||||
// Keep old code for reference
|
// Keep old code for reference
|
||||||
m_part =
|
m_part =
|
||||||
|
@ -593,19 +614,41 @@ public:
|
||||||
class ShaderBlender2 : public ShaderPart
|
class ShaderBlender2 : public ShaderPart
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShaderBlender2()
|
ShaderBlender2(const opengl::GLInfo & _glinfo)
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
m_part =
|
m_part =
|
||||||
" muxPM[0] = clampedColor; \n"
|
" srcColor2 = vec4(0.0); \n"
|
||||||
" muxPM[1] = vec4(0.0); \n"
|
" dstFactor2 = 0.0; \n"
|
||||||
" if (uForceBlendCycle2 != 0) { \n"
|
" muxPM[0] = srcColor1; \n"
|
||||||
" muxA[0] = clampedColor.a; \n"
|
" muxa = MUXA(uBlendMux2[1]); \n"
|
||||||
" muxB[0] = 1.0 - MUXA(uBlendMux2[1]); \n"
|
" muxB[0] = 1.0 - muxa; \n"
|
||||||
" lowp vec4 blend2 = MUXPM(uBlendMux2[0]) * MUXA(uBlendMux2[1]) + MUXPM(uBlendMux2[2]) * MUXB(uBlendMux2[3]); \n"
|
" muxb = MUXB(uBlendMux2[3]); \n"
|
||||||
" clampedColor.rgb = clamp(blend2.rgb, 0.0, 1.0); \n"
|
" muxp = MUXPM(uBlendMux2[0]); \n"
|
||||||
" } else clampedColor.rgb = (MUXPM(uBlendMux2[0])).rgb; \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
|
#else
|
||||||
// Keep old code for reference
|
// Keep old code for reference
|
||||||
m_part =
|
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
|
class ShaderLegacyBlender : public ShaderPart
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -871,7 +932,9 @@ public:
|
||||||
"highp vec2 texCoord1; \n"
|
"highp vec2 texCoord1; \n"
|
||||||
"highp vec2 tcData0[5]; \n"
|
"highp vec2 tcData0[5]; \n"
|
||||||
"highp vec2 tcData1[5]; \n"
|
"highp vec2 tcData1[5]; \n"
|
||||||
;
|
"uniform lowp int uCvgDest; \n"
|
||||||
|
"uniform lowp int uForceBlendAlpha; \n"
|
||||||
|
;
|
||||||
|
|
||||||
if (config.generalEmulation.enableLegacyBlending != 0) {
|
if (config.generalEmulation.enableLegacyBlending != 0) {
|
||||||
m_part +=
|
m_part +=
|
||||||
|
@ -924,15 +987,21 @@ public:
|
||||||
"IN lowp float vNumLights; \n"
|
"IN lowp float vNumLights; \n"
|
||||||
;
|
;
|
||||||
|
|
||||||
if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) {
|
if (_glinfo.dual_source_blending) {
|
||||||
m_part +=
|
m_part +=
|
||||||
"layout(location = 0) OUT lowp vec4 fragColor; \n"
|
"layout(location = 0, index = 0) OUT lowp vec4 fragColor; \n"
|
||||||
"layout(location = 1) inout highp vec4 depthZ; \n"
|
"layout(location = 0, index = 1) OUT lowp vec4 fragColor1; \n"
|
||||||
"layout(location = 2) inout highp vec4 depthDeltaZ; \n"
|
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
m_part +=
|
m_part +=
|
||||||
"OUT lowp vec4 fragColor; \n"
|
"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 highp float uPrimDepth; \n"
|
||||||
"uniform mediump vec2 uScreenScale; \n"
|
"uniform mediump vec2 uScreenScale; \n"
|
||||||
"uniform lowp int uScreenSpaceTriangle; \n"
|
"uniform lowp int uScreenSpaceTriangle; \n"
|
||||||
|
"uniform lowp int uCvgDest; \n"
|
||||||
|
"uniform lowp int uForceBlendAlpha; \n"
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
if (config.generalEmulation.enableLegacyBlending != 0) {
|
if (config.generalEmulation.enableLegacyBlending != 0) {
|
||||||
|
@ -1006,17 +1078,23 @@ public:
|
||||||
"IN lowp float vNumLights; \n"
|
"IN lowp float vNumLights; \n"
|
||||||
;
|
;
|
||||||
|
|
||||||
if (config.frameBufferEmulation.N64DepthCompare == Config::dcFast && _glinfo.ext_fetch) {
|
if (_glinfo.dual_source_blending) {
|
||||||
m_part +=
|
m_part +=
|
||||||
"layout(location = 0) OUT lowp vec4 fragColor; \n"
|
"layout(location = 0, index = 0) OUT lowp vec4 fragColor; \n"
|
||||||
"layout(location = 1) inout highp vec4 depthZ; \n"
|
"layout(location = 0, index = 1) OUT lowp vec4 fragColor1; \n"
|
||||||
"layout(location = 2) inout highp vec4 depthDeltaZ; \n"
|
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
m_part +=
|
m_part +=
|
||||||
"OUT lowp vec4 fragColor; \n"
|
"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) {
|
if (config.generalEmulation.enableLegacyBlending == 0) {
|
||||||
m_part =
|
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 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 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 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);
|
m_callDither->write(ssShader);
|
||||||
|
|
||||||
if (config.generalEmulation.enableLegacyBlending == 0) {
|
if (config.generalEmulation.enableLegacyBlending == 0) {
|
||||||
if (g_cycleType <= G_CYC_2CYCLE)
|
if (g_cycleType <= G_CYC_2CYCLE) {
|
||||||
m_blender1->write(ssShader);
|
m_blender1->write(ssShader);
|
||||||
if (g_cycleType == G_CYC_2CYCLE)
|
if (g_cycleType == G_CYC_2CYCLE)
|
||||||
m_blender2->write(ssShader);
|
m_blender2->write(ssShader);
|
||||||
|
m_blenderAlpha->write(ssShader);
|
||||||
|
} else
|
||||||
|
ssShader << " fragColor = clampedColor;" << std::endl;
|
||||||
|
|
||||||
ssShader << " fragColor = clampedColor;" << std::endl;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ssShader << " fragColor = clampedColor;" << std::endl;
|
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)
|
CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, opengl::CachedUseProgram * _useProgram)
|
||||||
: m_blender1(new ShaderBlender1)
|
: m_blender1(new ShaderBlender1(_glinfo))
|
||||||
, m_blender2(new ShaderBlender2)
|
, m_blender2(new ShaderBlender2(_glinfo))
|
||||||
|
, m_blenderAlpha (new ShaderBlenderAlpha(_glinfo))
|
||||||
, m_legacyBlender(new ShaderLegacyBlender)
|
, m_legacyBlender(new ShaderLegacyBlender)
|
||||||
, m_clamp(new ShaderClamp)
|
, m_clamp(new ShaderClamp)
|
||||||
, m_signExtendColorC(new ShaderSignExtendColorC)
|
, m_signExtendColorC(new ShaderSignExtendColorC)
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace glsl {
|
||||||
typedef std::unique_ptr<ShaderPart> ShaderPartPtr;
|
typedef std::unique_ptr<ShaderPart> ShaderPartPtr;
|
||||||
ShaderPartPtr m_blender1;
|
ShaderPartPtr m_blender1;
|
||||||
ShaderPartPtr m_blender2;
|
ShaderPartPtr m_blender2;
|
||||||
|
ShaderPartPtr m_blenderAlpha;
|
||||||
ShaderPartPtr m_legacyBlender;
|
ShaderPartPtr m_legacyBlender;
|
||||||
ShaderPartPtr m_clamp;
|
ShaderPartPtr m_clamp;
|
||||||
ShaderPartPtr m_signExtendColorC;
|
ShaderPartPtr m_signExtendColorC;
|
||||||
|
|
|
@ -369,30 +369,33 @@ public:
|
||||||
const int forceBlend2 = gDP.otherMode.forceBlender;
|
const int forceBlend2 = gDP.otherMode.forceBlender;
|
||||||
uForceBlendCycle2.set(forceBlend2, _force);
|
uForceBlendCycle2.set(forceBlend2, _force);
|
||||||
|
|
||||||
// Modes, which shader blender can't emulate
|
if (!graphics::Context::DualSourceBlending) {
|
||||||
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
|
// Modes, which shader blender can't emulate
|
||||||
switch (mode) {
|
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
|
||||||
case 0x0040:
|
switch (mode) {
|
||||||
// Mia Hamm Soccer
|
case 0x0040:
|
||||||
// clr_in * a_in + clr_mem * (1-a)
|
// Mia Hamm Soccer
|
||||||
// clr_in * a_in + clr_in * (1-a)
|
// clr_in * a_in + clr_mem * (1-a)
|
||||||
case 0x0050:
|
// clr_in * a_in + clr_in * (1-a)
|
||||||
// A Bug's Life
|
case 0x0050:
|
||||||
// clr_in * a_in + clr_mem * (1-a)
|
// A Bug's Life
|
||||||
// clr_in * a_in + clr_mem * (1-a)
|
// clr_in * a_in + clr_mem * (1-a)
|
||||||
uForceBlendCycle1.set(0, _force);
|
// clr_in * a_in + clr_mem * (1-a)
|
||||||
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);
|
uForceBlendCycle1.set(0, _force);
|
||||||
uForceBlendCycle2.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:
|
private:
|
||||||
|
@ -402,6 +405,24 @@ private:
|
||||||
iUniform uForceBlendCycle2;
|
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
|
class UDitherMode : public UniformGroup
|
||||||
{
|
{
|
||||||
public:
|
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 UDitherMode(_program, _inputs.usesNoise()));
|
||||||
|
|
||||||
_uniforms.emplace_back(new UScreenScale(_program));
|
_uniforms.emplace_back(new UScreenScale(_program));
|
||||||
|
|
|
@ -313,8 +313,7 @@ namespace glsl {
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" TEX_FILTER(fragColor, uTex0, vTexCoord0); \n"
|
" TEX_FILTER(fragColor, uTex0, vTexCoord0); \n"
|
||||||
;
|
;
|
||||||
if (!_glinfo.isGLES2 &&
|
if (config.generalEmulation.enableFragmentDepthWrite != 0 &&
|
||||||
config.generalEmulation.enableFragmentDepthWrite != 0 &&
|
|
||||||
config.frameBufferEmulation.N64DepthCompare == Config::dcDisable) {
|
config.frameBufferEmulation.N64DepthCompare == Config::dcDisable) {
|
||||||
m_part +=
|
m_part +=
|
||||||
" gl_FragDepth = uPrimDepth; \n"
|
" 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)
|
void ContextImpl::setBlending(graphics::BlendParam _sfactor, graphics::BlendParam _dfactor)
|
||||||
{
|
{
|
||||||
m_cachedFunctions->getCachedBlending()->setBlending(_sfactor, _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)
|
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->getCachedBlendingSeparate()->setBlendingSeparate(_sfactorcolor, _dfactorcolor, _sfactoralpha, _dfactoralpha);
|
||||||
|
m_cachedFunctions->getCachedBlending()->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextImpl::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
|
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;
|
return m_glInfo.eglImage;
|
||||||
case graphics::SpecialFeatures::EglImageFramebuffer:
|
case graphics::SpecialFeatures::EglImageFramebuffer:
|
||||||
return m_glInfo.eglImageFramebuffer;
|
return m_glInfo.eglImageFramebuffer;
|
||||||
|
case graphics::SpecialFeatures::DualSourceBlending:
|
||||||
|
return m_glInfo.dual_source_blending;
|
||||||
}
|
}
|
||||||
return false;
|
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;
|
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"));
|
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
|
#ifdef OS_ANDROID
|
||||||
eglImage = eglImage &&
|
eglImage = eglImage &&
|
||||||
( (isGLES2 && GraphicBufferWrapper::isSupportAvailable()) || (isGLESX && GraphicBufferWrapper::isPublicSupportAvailable()) ) &&
|
( (isGLES2 && GraphicBufferWrapper::isSupportAvailable()) || (isGLESX && GraphicBufferWrapper::isPublicSupportAvailable()) ) &&
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct GLInfo {
|
||||||
bool ext_fetch = false;
|
bool ext_fetch = false;
|
||||||
bool eglImage = false;
|
bool eglImage = false;
|
||||||
bool eglImageFramebuffer = false;
|
bool eglImageFramebuffer = false;
|
||||||
|
bool dual_source_blending = false;
|
||||||
Renderer renderer = Renderer::Other;
|
Renderer renderer = Renderer::Other;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
|
@ -117,6 +117,10 @@ namespace graphics {
|
||||||
BlendParam ONE_MINUS_SRC_ALPHA(GL_ONE_MINUS_SRC_ALPHA);
|
BlendParam ONE_MINUS_SRC_ALPHA(GL_ONE_MINUS_SRC_ALPHA);
|
||||||
BlendParam CONSTANT_ALPHA(GL_CONSTANT_ALPHA);
|
BlendParam CONSTANT_ALPHA(GL_CONSTANT_ALPHA);
|
||||||
BlendParam ONE_MINUS_CONSTANT_ALPHA(GL_ONE_MINUS_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 {
|
namespace drawmode {
|
||||||
|
|
|
@ -117,6 +117,10 @@ namespace graphics {
|
||||||
extern BlendParam ONE_MINUS_SRC_ALPHA;
|
extern BlendParam ONE_MINUS_SRC_ALPHA;
|
||||||
extern BlendParam CONSTANT_ALPHA;
|
extern BlendParam CONSTANT_ALPHA;
|
||||||
extern BlendParam ONE_MINUS_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 {
|
namespace drawmode {
|
||||||
|
|
|
@ -314,8 +314,7 @@ void GraphicsDrawer::_updateScreenCoordsViewport(const FrameBuffer * _pBuffer) c
|
||||||
gSP.changed |= CHANGED_VIEWPORT;
|
gSP.changed |= CHANGED_VIEWPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
void GraphicsDrawer::_legacyBlending() const
|
||||||
void _legacySetBlendMode()
|
|
||||||
{
|
{
|
||||||
const u32 blendmode = gDP.otherMode.l >> 16;
|
const u32 blendmode = gDP.otherMode.l >> 16;
|
||||||
// 0x7000 = CVG_X_ALPHA|ALPHA_CVG_SEL|FORCE_BL
|
// 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
|
// Set unsupported blend modes
|
||||||
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
|
if (gDP.otherMode.cycleType == G_CYC_2CYCLE) {
|
||||||
switch (mode) {
|
const u32 mode = _SHIFTR(gDP.otherMode.l, 16, 16);
|
||||||
case 0x0040:
|
switch (mode) {
|
||||||
// Mia Hamm Soccer
|
case 0x0040:
|
||||||
// clr_in * a_in + clr_mem * (1-a)
|
// Mia Hamm Soccer
|
||||||
// clr_in * a_in + clr_in * (1-a)
|
// clr_in * a_in + clr_mem * (1-a)
|
||||||
case 0x0050:
|
// clr_in * a_in + clr_in * (1-a)
|
||||||
// A Bug's Life
|
case 0x0050:
|
||||||
// clr_in * a_in + clr_mem * (1-a)
|
// 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);
|
// clr_in * a_in + clr_mem * (1-a)
|
||||||
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) {
|
|
||||||
gfxContext.enable(enable::BLEND, true);
|
gfxContext.enable(enable::BLEND, true);
|
||||||
gfxContext.setBlending(blend::SRC_ALPHA, blend::ONE_MINUS_SRC_ALPHA);
|
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) {
|
if (gDP.otherMode.forceBlender != 0 && gDP.otherMode.cycleType < G_CYC_COPY) {
|
||||||
BlendParam srcFactor = blend::ONE;
|
BlendParam srcFactor = blend::ONE;
|
||||||
|
@ -535,7 +522,8 @@ void GraphicsDrawer::_setBlendMode() const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memFactorSource = 0;
|
memFactorSource = 0;
|
||||||
} else if (gDP.otherMode.c2_m2a == 1) {
|
}
|
||||||
|
else if (gDP.otherMode.c2_m2a == 1) {
|
||||||
memFactorSource = 1;
|
memFactorSource = 1;
|
||||||
}
|
}
|
||||||
if (gDP.otherMode.c2_m2a == 0 && gDP.otherMode.c2_m2b == 1) {
|
if (gDP.otherMode.c2_m2a == 0 && gDP.otherMode.c2_m2b == 1) {
|
||||||
|
@ -552,8 +540,7 @@ void GraphicsDrawer::_setBlendMode() const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memFactorSource = 0;
|
memFactorSource = 0;
|
||||||
}
|
} else if (gDP.otherMode.c1_m2a == 1) {
|
||||||
else if (gDP.otherMode.c1_m2a == 1) {
|
|
||||||
memFactorSource = 1;
|
memFactorSource = 1;
|
||||||
}
|
}
|
||||||
if (gDP.otherMode.c1_m2a == 0 && gDP.otherMode.c1_m2b == 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
|
void GraphicsDrawer::_updateTextures() const
|
||||||
{
|
{
|
||||||
//For some reason updating the texture cache on the first frame of LOZ:OOT causes a nullptr Pointer exception...
|
//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))) {
|
if ((gDP.changed & (CHANGED_RENDERMODE | CHANGED_CYCLETYPE))) {
|
||||||
_setBlendMode();
|
setBlendMode();
|
||||||
gDP.changed &= ~(CHANGED_RENDERMODE | CHANGED_CYCLETYPE);
|
gDP.changed &= ~(CHANGED_RENDERMODE | CHANGED_CYCLETYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,7 +1090,7 @@ bool texturedRectShadowMap(const GraphicsDrawer::TexturedRectParams &)
|
||||||
pCurrentBuffer->m_pDepthBuffer->activateDepthBufferTexture(pCurrentBuffer);
|
pCurrentBuffer->m_pDepthBuffer->activateDepthBufferTexture(pCurrentBuffer);
|
||||||
CombinerInfo::get().setDepthFogCombiner();
|
CombinerInfo::get().setDepthFogCombiner();
|
||||||
// DepthFogCombiner does not support shader blending.
|
// DepthFogCombiner does not support shader blending.
|
||||||
_legacySetBlendMode();
|
dwnd().getDrawer().setBlendMode(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,8 @@ public:
|
||||||
|
|
||||||
void setBackgroundDrawingMode(bool _mode) { m_bBGMode = _mode; }
|
void setBackgroundDrawingMode(bool _mode) { m_bBGMode = _mode; }
|
||||||
|
|
||||||
|
void setBlendMode(bool _forceLegacyBlending = false) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class DisplayWindow;
|
friend class DisplayWindow;
|
||||||
friend TexrectDrawer;
|
friend TexrectDrawer;
|
||||||
|
@ -173,8 +175,9 @@ private:
|
||||||
|
|
||||||
void _setSpecialTexrect() const;
|
void _setSpecialTexrect() const;
|
||||||
|
|
||||||
void _setBlendMode() const;
|
void _legacyBlending() const;
|
||||||
bool _setUnsupportedBlendMode() const;
|
void _ordinaryBlending() const;
|
||||||
|
void _dualSourceBlending() const;
|
||||||
void _updateCullFace() const;
|
void _updateCullFace() const;
|
||||||
void _updateViewport() const;
|
void _updateViewport() const;
|
||||||
void _updateScreenCoordsViewport(const FrameBuffer * _pBuffer = nullptr) const;
|
void _updateScreenCoordsViewport(const FrameBuffer * _pBuffer = nullptr) const;
|
||||||
|
|
|
@ -350,7 +350,7 @@ bool TexrectDrawer::draw()
|
||||||
ValueKeeper<gDPScissor> scissor(gDP.scissor, m_scissor);
|
ValueKeeper<gDPScissor> scissor(gDP.scissor, m_scissor);
|
||||||
DisplayWindow & wnd = dwnd();
|
DisplayWindow & wnd = dwnd();
|
||||||
GraphicsDrawer & drawer = wnd.getDrawer();
|
GraphicsDrawer & drawer = wnd.getDrawer();
|
||||||
drawer._setBlendMode();
|
drawer.setBlendMode();
|
||||||
gDP.changed |= CHANGED_RENDERMODE; // Force update of depth compare parameters
|
gDP.changed |= CHANGED_RENDERMODE; // Force update of depth compare parameters
|
||||||
drawer._updateDepthCompare();
|
drawer._updateDepthCompare();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user