Page 1 of 1
Blackened pixels due to filtering problem
Posted: Fri Nov 03, 2023 4:52 pm
by Nickak2003
Hello, I have a manual image which I am rendering to screen. This image is square, but some pixels should not be rendered, and are therefore alpha=0. This seems to work. The problem is that the filtering is blending these pixels (black+transparent) into the colored visible pixels, darkening them. I tried disabling filtering like so:
Code: Select all
void createDataBlock(Graphics& graphics) {
static std::size_t idCounter = 0;
Ogre::HlmsManager* hlmsManager = graphics.getRoot()->getHlmsManager();
Ogre::HlmsUnlit* hlmsUnlit = static_cast<Ogre::HlmsUnlit*>(hlmsManager->getHlms(Ogre::HLMS_UNLIT));
Ogre::HlmsMacroblock macroBlock;
macroBlock.mDepthCheck = false;
Ogre::HlmsBlendblock blendBlock;
blendBlock.setBlendType(Ogre::SceneBlendType::SBT_TRANSPARENT_ALPHA);
mName = "ManualTextureBox" + std::to_string(idCounter++);
mDataBlock = static_cast<Ogre::HlmsUnlitDatablock*>(
hlmsUnlit->createDatablock(mName,
mName,
macroBlock,
blendBlock,
Ogre::HlmsParamVec()
));
mDataBlock->setTexture(0, mManualTexture.getTexture());
Ogre::HlmsSamplerblock samplerblock;
samplerblock.mU = Ogre::TextureAddressingMode::TAM_WRAP;
samplerblock.mV = Ogre::TextureAddressingMode::TAM_WRAP;
samplerblock.mW = Ogre::TextureAddressingMode::TAM_WRAP;
samplerblock.mMaxAnisotropy = 0;
samplerblock.mMagFilter = Ogre::FO_NONE;
samplerblock.mMinFilter = Ogre::FO_NONE;
samplerblock.mMipFilter = Ogre::FO_NONE;
samplerblock.setFiltering(Ogre::TextureFilterOptions::TFO_NONE);
mDataBlock->setSamplerblock(Ogre::TextureTypes::Type2D, samplerblock);
}
However, this does not work. This is what the troublesome area of the image looks like:
https://pasteboard.co/PKjyGzE7V3eH.png
How can this be resolved?
Re: Blackened pixels due to filtering problem
Posted: Fri Nov 03, 2023 7:48 pm
by dark_sylinc
What you're experiencing is solved using premultiplied alpha blending.
The algorithm consists in multiplying your texture rgb * a before saving to disk (or to RAM); and then setting the blend type to:
Code: Select all
blendblock.mSourceBlendFactor = Ogre::SBF_ONE;
blendblock.mDestBlendFactor = Ogre::SBF_ONE_MINUS_SOURCE_ALPHA;
blendblock.mSourceBlendFactorAlpha = blendblock.mSourceBlendFactor;
blendblock.mDestBlendFactorAlpha = blendblock.mDestBlendFactor;
But as the blog post describes, there are other side effects and it's a different mindset (because alpha = 0 no longer means "fully transparent", fully transparent is achieved when both rgb = 0 and alpha = 0)
Re: Blackened pixels due to filtering problem
Posted: Sat Nov 04, 2023 3:04 pm
by Nickak2003
OK, these textures are manually generated each frame, using code like:
Code: Select all
*reinterpret_cast<uint32_t* RESTRICT_ALIAS>(texBox.at(x, y, 0)) = v;
I guess I don't quite understand what you mean by "multiplying your texture rgb * a before saving to disk (or to RAM)".
Is all I need to do is change the blend block and maintain alpha == 0 and color == 0 to get the desired effect?
Re: Blackened pixels due to filtering problem
Posted: Sat Nov 04, 2023 5:32 pm
by dark_sylinc
Then you need to do:
Code: Select all
col.r *= col.a;
col.g *= col.a;
col.b *= col.a;
v = col.getAsRGBA(); //or getAsABGR or whatever
*reinterpret_cast<uint32_t* RESTRICT_ALIAS>(texBox.at(x, y, 0)) = v;
And set the blendblock to the mode I described above.
Re: Blackened pixels due to filtering problem
Posted: Fri Nov 10, 2023 4:04 pm
by Nickak2003
My friend, this does not appear to be working out, it is still darkening. Here are my various code segments:
Code: Select all
Ogre::HlmsManager* hlmsManager = graphics.getRoot()->getHlmsManager();
Ogre::HlmsUnlit* hlmsUnlit = static_cast<Ogre::HlmsUnlit*>(hlmsManager->getHlms(Ogre::HLMS_UNLIT));
Ogre::HlmsMacroblock macroBlock;
macroBlock.mDepthCheck = false;
Ogre::HlmsBlendblock blendBlock;
// blendBlock.setBlendType(Ogre::SceneBlendType::SBT_TRANSPARENT_ALPHA);
blendBlock.mSourceBlendFactor = Ogre::SBF_ONE;
blendBlock.mDestBlendFactor = Ogre::SBF_ONE_MINUS_SOURCE_ALPHA;
blendBlock.mSourceBlendFactorAlpha = blendBlock.mSourceBlendFactor;
blendBlock.mDestBlendFactorAlpha = blendBlock.mDestBlendFactor;
mName = "ManualTextureBox" + std::to_string(idCounter++);
mDataBlock = static_cast<Ogre::HlmsUnlitDatablock*>(
hlmsUnlit->createDatablock(mName,
mName,
macroBlock,
blendBlock,
Ogre::HlmsParamVec()
));
mDataBlock->setTexture(0, mManualTexture.getTexture());
each frame, the following code is called for each pixel:
Code: Select all
color.setAsABGR(Ogre::ABGR(mConvertedWeights[i]));
//premulitply alpha to prevent transparnt-black from blending affecting output layer
color.r *= color.a;
color.g *= color.a;
color.b *= color.a;
*reinterpret_cast<uint32_t* RESTRICT_ALIAS>(texBox.at(x, y, 0)) = color.getAsABGR();
I have verified that the pixels which should be black are indeed argb == 0.
the texture, which is attached to a manual object ( quad + identiy view/proj), is created with this flag:
Code: Select all
Ogre::PixelFormatGpu::PFG_RGBA8_UNORM_SRGB
Re: Blackened pixels due to filtering problem
Posted: Fri Nov 10, 2023 11:20 pm
by dark_sylinc
Maybe I understood incorrectly what you're trying to achieve? Could you post in Photoshop/GIMP what you were hoping to achieve?