Skip to content

Commit

Permalink
Rethink 2x src alpha->color doubling. Fixes #3379.
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Mar 29, 2014
1 parent 04bcbfb commit 47efded
Showing 1 changed file with 12 additions and 34 deletions.
46 changes: 12 additions & 34 deletions GPU/GLES/FragmentShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,33 +234,14 @@ static bool IsColorTestTriviallyTrue() {
}
}

static bool CanDoubleSrcBlendMode() {
static bool AlphaToColorDoubling() {
if (!gstate.isAlphaBlendEnabled()) {
return false;
}

int funcA = gstate.getBlendFuncA();
int funcB = gstate.getBlendFuncB();
if (funcA != GE_SRCBLEND_DOUBLESRCALPHA) {
funcB = funcA;
funcA = gstate.getBlendFuncB();
}
if (funcA != GE_SRCBLEND_DOUBLESRCALPHA) {
return false;
}

// One side should be doubled. Let's check the other side.
// LittleBigPlanet, for example, uses 2.0 * src, 1.0 - src, which can't double.
// Persona 2 uses the same function, which is the reason for its darkness. It only ever passes
// 1.0 as src alpha though, so in effect it's a color doubling.
switch (funcB) {
case GE_DSTBLEND_SRCALPHA:
case GE_DSTBLEND_INVSRCALPHA:
return false;

default:
return true;
}
// 2x alpha in the source function = source color doubling.
// We don't really need to care about the dest alpha function - sure we can't handle
// the doubling dest ones, but there's nothing we can do about that.
return (gstate.getBlendFuncA() == GE_SRCBLEND_DOUBLESRCALPHA);
}

// Here we must take all the bits of the gstate that determine what the fragment shader will
Expand All @@ -275,9 +256,8 @@ void ComputeFragmentShaderID(FragmentShaderID *id) {
bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough();
bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue() && !g_Config.bDisableAlphaTest;
bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue();
bool enableColorDoubling = gstate.isColorDoublingEnabled();
bool enableColorDoubling = gstate.isColorDoublingEnabled() || AlphaToColorDoubling();
// This isn't really correct, but it's a hack to get doubled blend modes to work more correctly.
bool enableAlphaDoubling = CanDoubleSrcBlendMode();
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doTextureAlpha = gstate.isTextureAlphaUsed();
ReplaceAlphaType stencilToAlpha = ReplaceAlphaWithStencil();
Expand All @@ -303,7 +283,6 @@ void ComputeFragmentShaderID(FragmentShaderID *id) {
id->d[0] |= (enableFog & 1) << 15;
id->d[0] |= (doTextureProjection & 1) << 16;
id->d[0] |= (enableColorDoubling & 1) << 17;
id->d[0] |= (enableAlphaDoubling & 1) << 18;
id->d[0] |= (stencilToAlpha) << 19;

if (stencilToAlpha != REPLACE_ALPHA_NO) {
Expand Down Expand Up @@ -381,9 +360,12 @@ void GenerateFragmentShader(char *buffer) {
bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear();
bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue() && !gstate.isModeClear() && !g_Config.bDisableAlphaTest;
bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && !gstate.isModeClear();
bool enableColorDoubling = gstate.isColorDoublingEnabled() && gstate.isTextureMapEnabled();

// If alpha doubling is enabled, we double the color value instead. Otherwise alpha 255 doubled will have no effect.
// TODO: Why the texturemapenabled check?

This comment has been minimized.

Copy link
@unknownbrackets

unknownbrackets Mar 29, 2014

Collaborator

Color doubling only happens when texture mapping is enabled. It's actually a texture bit.

-[Unknown]

This comment has been minimized.

Copy link
@hrydgard

hrydgard Mar 29, 2014

Author Owner

Ah, right. Then we should check the same way in the ID generator...

bool enableColorDoubling = (gstate.isColorDoublingEnabled() && gstate.isTextureMapEnabled()) || AlphaToColorDoubling();

// This isn't really correct, but it's a hack to get doubled blend modes to work more correctly.
bool enableAlphaDoubling = CanDoubleSrcBlendMode();
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doTextureAlpha = gstate.isTextureAlphaUsed();
ReplaceAlphaType stencilToAlpha = ReplaceAlphaWithStencil();
Expand Down Expand Up @@ -547,12 +529,8 @@ void GenerateFragmentShader(char *buffer) {
}

// Color doubling happens after the color test.
if (enableColorDoubling && enableAlphaDoubling) {
WRITE(p, " v = v * 2.0;\n");
} else if (enableColorDoubling) {
if (enableColorDoubling) {
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
} else if (enableAlphaDoubling) {
WRITE(p, " v.a = v.a * 2.0;\n");
}

if (enableFog) {
Expand Down

7 comments on commit 47efded

@dbz400
Copy link
Contributor

@dbz400 dbz400 commented on 47efded Mar 29, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Humm probably some cases got broken . for example Super Robot War A portable which use double alpha blending a lot.

It uses 2.0 * src.a , 1 - 2.0 * src.a

uljs00143_00000

Previous build
uljs00143_00001

@hrydgard
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agh, okay. Will look at this some more.

@dbz400
Copy link
Contributor

@dbz400 dbz400 commented on 47efded Mar 29, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was very nice to get 2x src blending working now in Persona 2 .

@hrydgard
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Committed a new attempt, where I keep most of the old logic too. Can you test?

@dbz400
Copy link
Contributor

@dbz400 dbz400 commented on 47efded Mar 29, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep work prefectly now !

@dbz400
Copy link
Contributor

@dbz400 dbz400 commented on 47efded Mar 29, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just seen DepalettizeShader.ccp & h . Is it using for translating the palette ?

@hrydgard
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, oops. Those weren't meant to get commited yet.

Please sign in to comment.