Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed an issue where the shader would come off when run setTexture. #20603

Open
wants to merge 3 commits into
base: v4
Choose a base branch
from

Conversation

HirokiIshimori
Copy link

@HirokiIshimori HirokiIshimori commented Oct 22, 2020

Summary

Fix issue #20600 , When I set a shader in Sprite and execute setTexture, the shader comes off.

Event

  1. After doing setProgramState as below ...
sprite->setProgramState(programState);
  1. Try calling setTexture.
sprite->setTexture(filePath);

Then the shader will not run.

Why I submitted a Pull Request.

Currently, it can be dealt with by calling setProgramState immediately after calling setTexture as shown below.

sprite->setTexture(filePath);
sprite->setProgramState(mProgramState);

But developers need to explicitly keep ProgramState, and I think it's a redundant implementation.
So I submitted a Pull Request.

Copy link
Contributor

@halx99 halx99 left a comment

Choose a reason for hiding this comment

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

I think, check does custom shader is better

@HirokiIshimori
Copy link
Author

Does a custom shader solve this problem?

@halx99
Copy link
Contributor

halx99 commented Oct 26, 2020

Does a custom shader solve this problem?

Please refer to this commit: axmolengine/axmol@27bdca3

@HirokiIshimori
Copy link
Author

Thank you very much. I pushed a fix commit.
6e3d316

@rh101
Copy link
Contributor

rh101 commented Oct 27, 2020

The added condition _programState->getProgram()->getProgramType() == backend::ProgramType::POSITION_TEXTURE_COLOR has no effect if it's the same, but also it won't correctly set the ETC1 shader if the new texture is of format ETC1:

    if (_programState == nullptr || _programState->getProgram()->getProgramType() == backend::ProgramType::POSITION_TEXTURE_COLOR) {
        const auto isETC1 = texture && texture->getAlphaTextureName();
        setProgramState((isETC1) ? backend::ProgramType::ETC1 : backend::ProgramType::POSITION_TEXTURE_COLOR);
    }

because setProgramState checks if it's the same type, and returns if it is, so it changes nothing:

void Sprite::setProgramState(unsigned type)
{
    if(_programState != nullptr &&
       _programState->getProgram()->getProgramType() == type)
        return;
    
    auto* program = backend::Program::getBuiltinProgram(type);
    auto programState = new (std::nothrow) backend::ProgramState(program);
    setProgramState(programState);
    CC_SAFE_RELEASE_NULL(programState);
}

This would probably work better, and what @halx99 may have meant:

 if (_programState == nullptr || _programState->getProgram()->getProgramType() < backend::ProgramType::CUSTOM_PROGRAM) {
        const auto isETC1 = texture && texture->getAlphaTextureName();
        setProgramState((isETC1) ? backend::ProgramType::ETC1 : backend::ProgramType::POSITION_TEXTURE_COLOR);
    }

It would then correctly set the ETC1 or POSITION_TEXTURE_COLOR shader depending on the passed in texture, and it won't affect sprites with custom shaders.

Otherwise, you can explicitly check for the ETC1 and POSITION_TEXTURE_COLOR shaders, in case a non-custom shader is being used on the sprite that isn't one of them:

if (_programState == nullptr || _programState->getProgram()->getProgramType() == backend::ProgramType::POSITION_TEXTURE_COLOR || 
    _programState->getProgram()->getProgramType() == backend::ProgramType::ETC1) {
    const auto isETC1 = texture && texture->getAlphaTextureName();
    setProgramState((isETC1) ? backend::ProgramType::ETC1 : backend::ProgramType::POSITION_TEXTURE_COLOR);
}

@halx99
Copy link
Contributor

halx99 commented Oct 27, 2020

Yes, @rh101 's code is better

Comment on lines 420 to 423
if (_programState == nullptr || _programState->getProgram()->getProgramType() == backend::ProgramType::POSITION_TEXTURE_COLOR) {
const auto isETC1 = texture && texture->getAlphaTextureName();
setProgramState((isETC1) ? backend::ProgramType::ETC1 : backend::ProgramType::POSITION_TEXTURE_COLOR);
}
Copy link
Author

Choose a reason for hiding this comment

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

Thank you for your advice.

Is it okay with such a fix?

Suggested change
if (_programState == nullptr || _programState->getProgram()->getProgramType() == backend::ProgramType::POSITION_TEXTURE_COLOR) {
const auto isETC1 = texture && texture->getAlphaTextureName();
setProgramState((isETC1) ? backend::ProgramType::ETC1 : backend::ProgramType::POSITION_TEXTURE_COLOR);
}
if (_programState == nullptr || _programState->getProgram()->getProgramType() == backend::ProgramType::POSITION_TEXTURE_COLOR ||
_programState->getProgram()->getProgramType() == backend::ProgramType::ETC1) {
const auto isETC1 = texture && texture->getAlphaTextureName();
setProgramState((isETC1) ? backend::ProgramType::ETC1 : backend::ProgramType::POSITION_TEXTURE_COLOR);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes that would work fine, since it covers all cases.

@HirokiIshimori
Copy link
Author

@halx99 @rh101 Thank you.

zhongfq added a commit to zhongfq/cocos-lua that referenced this pull request Nov 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants