How to add a transparent material on top of a submesh

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
cc9cii
Halfling
Posts: 99
Joined: Tue Sep 18, 2018 4:53 am
x 20

How to add a transparent material on top of a submesh

Post by cc9cii »

Ogre Version: 1.10
Operating System: Windows
Render System: D3D9

Hi, I'm trying to do something like https://www.wikihow.com/Use-V.A.T.S.-in ... sion-2.jpg.

I've tried adding a pass with a greenish texture but the result is not very satisfactory - (a) sometimes the underlying pass with diffuse texture bleeds through depending on the viewing angle and (b) I can't seem to achieve the transparent look.

Is there a better way?

EDIT: what I am doing

Code: Select all

Ogre::MaterialPtr mat = xxxxx;
Ogre::Material::TechniqueIterator techIter = mat->getTechniqueIterator();
while(techIter.hasMoreElements())
{
    Ogre::Technique *tech = techIter.getNext();
    Ogre::Pass *pass = tech->createPass();
    pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
    Ogre::TextureUnitState *newTUS = pass->createTextureUnitState("DynamicTransGreen");
    newTUS->setAlphaOperation(Ogre::LBX_BLEND_TEXTURE_ALPHA);
}
rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 353

Re: How to add a transparent material on top of a submesh

Post by rpgplayerrobin »

First of all, if there is a sorting issue between the first pass and the second pass, you can try to apply a depth bias to it:

Code: Select all

getTechnique(x)->getPass(y)->setDepthBias(1.0f); // You can make the value higher of course

https://ogrecave.github.io/ogre/api/13/ ... otoc_md130

I just do this to create a new pass on a material that should have a texture that supports transparency on it:

Code: Select all

Pass* tmpNewPass = tmpTechnique->createPass();
tmpNewPass->setDepthBias(tmpDepthBias);
tmpNewPass->setSceneBlending(SceneBlendType::SBT_TRANSPARENT_ALPHA);
TextureUnitState* tmpNewTextureUnitState = tmpNewPass->createTextureUnitState(tmpDiffuseTextureName);

So I don't do the last line that you do (I don't even find a single search result for "LBX_BLEND_TEXTURE_ALPHA" in my huge game code-base, so it is never needed it seems like?).

It seems their technique is a fullscreen effect (compositor, which are expensive), since it bleeds outside of the original mesh.
To do that in Ogre, you need to create a new technique and a pass for that in the material, then set that new techniques Material Scheme.
Then you need to render only that material scheme in a compositor and handle its appearance through a shader.

Or, you can just skip the special effects and bleeding away from the original mesh and skip the compositor route.
I would then just do a new pass like you are doing, set the depth bias and then apply a special shader to the pass.
Then that shader should have a texture input which is a texturemap of the mesh (in your case, the character) where the effect should actually happen (the same kind of a map like how it is normally textured with UV:s).
Then the shader checks if the current pixel is actually in the area where the effect can happen (read the pixel and see if it is not black for example) and then it should either use "discard;" if it fails or it should handle the greenish appearance if it succeeds.
The greenish appearance can be made by another texture that is the green pattern, or the texturemap above that handles where the effect is shown can just be the greenish pattern, which will be much simpler since you just have to add it to the base diffusemap texture, but then you can't do fancy effects such as texture scrolling and such.

If you did not mean the greenish pattern, but the outline, there are a billion articles on how to do an outline shader online (some expensive, some not).

User avatar
cc9cii
Halfling
Posts: 99
Joined: Tue Sep 18, 2018 4:53 am
x 20

Re: How to add a transparent material on top of a submesh

Post by cc9cii »

Hi, thanks for your quick reply. Setting a depth bias solved the "bleeding" problem. Yay!

But my supposedly "transparent" texture is not transparent at all. It looks like this
EDIT: sorry, I had wrong alpha value in the manually created texture, using a smaller value of 90 yields a better result

Image

Image

Your suggestion of creating a shader sounds promising and I will work on it - but it will take me weeks to study a new area and get things going so in the meantime I would like to get a temporary workaround just using a texture and pass. Not sure if it is relevant but the area to be highlighted is a sub-mesh so UV mapping is probably unnecessary.

The texture was created manually:

Code: Select all

        texture = Ogre::TextureManager::getSingleton().createManual(
            "DynamicTransGreen", // name
            Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
            Ogre::TEX_TYPE_2D,  // type
            8, 8,               // width & height
            0,                  // number of mipmaps
            Ogre::PF_BYTE_BGRA, // pixel format
            Ogre::TU_DEFAULT);  // usage; should be TU_DYNAMIC_WRITE_ONLY_DISCARDABLE for
                                // textures updated very often (e.g. each frame)

    Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();
    pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL);
    const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();

    Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);

    for (size_t j = 0; j < 8; j++)
    {
        for(size_t i = 0; i < 8; i++)
        {
            *pDest++ = 125; // B
            *pDest++ = 198; // G
            *pDest++ =   0; // R
            *pDest++ = 248; // A
        }

        pDest += pixelBox.getRowSkip() * Ogre::PixelUtil::getNumElemBytes(pixelBox.format);
    }
    pixelBuffer->unlock();
Last edited by cc9cii on Fri Sep 23, 2022 12:08 am, edited 1 time in total.
rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 353

Re: How to add a transparent material on top of a submesh

Post by rpgplayerrobin »

The code I wrote should work even for fixed function pipeline (no shaders).

Try to apply a real texture to it instead, a loaded one from disk that you know has alpha (like a .png or .tga with alpha).
If that works, it means your code to create the texture is wrong.

Last edited by rpgplayerrobin on Fri Sep 23, 2022 12:11 am, edited 3 times in total.
User avatar
cc9cii
Halfling
Posts: 99
Joined: Tue Sep 18, 2018 4:53 am
x 20

Re: How to add a transparent material on top of a submesh

Post by cc9cii »

it means your code to create the texture is wrong.

Yes, I had the alpha value wrong :oops:

Thanks again for your help. I'll go study your other suggestion now.

rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 353

Re: How to add a transparent material on top of a submesh

Post by rpgplayerrobin »

Writing/reading textures are very hard. They usually don't show up in memory perfectly and I have had many issues with them (but always solved them in the end).
For example, PF_BYTE_BGRA is a weird format. In my version it defaults to PF_A8R8G8B8 in the code, which means that the alpha in that is actually first and not last. I would also suggest you to use PixelUtil::packColour instead.

Try something like this code:

Code: Select all

// Create the texture
TexturePtr m_texture = TextureManager::getSingleton().createManual(CGeneric::GenerateUniqueName(),
	ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
	TEX_TYPE_2D,
	8,
	8,
	0,
	PF_R8G8B8A8,
	TU_DYNAMIC);

// Loop through all pixels in the texture
Ogre::HardwarePixelBufferSharedPtr tmpHardwarePixelBuffer = m_texture->getBuffer(0, 0);
tmpHardwarePixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
const Ogre::PixelBox &tmpPixelBox = tmpHardwarePixelBuffer->getCurrentLock();
unsigned char* tmpData = static_cast<unsigned char*>(tmpPixelBox.data);
size_t tmpHeight = tmpPixelBox.getHeight();
size_t tmpDataIndex = 0;
size_t tmpDataIndexStep = PixelUtil::getNumElemBytes(tmpPixelBox.format);
for (size_t y = 0; y < tmpHeight; ++y)
{
	// Set the new pixel data
	PixelUtil::packColour(ColourValue(1.0f, 1.0f, 1.0f, 1.0f), tmpPixelBox.format, tmpData + tmpDataIndex);
	tmpDataIndex += tmpPixelBox.rowPitch * tmpDataIndexStep;
}
tmpHardwarePixelBuffer->unlock();

You answered too quickly :D
I am not sure if you saw my edited post above now haha.

Last edited by rpgplayerrobin on Fri Sep 23, 2022 8:07 pm, edited 1 time in total.
User avatar
cc9cii
Halfling
Posts: 99
Joined: Tue Sep 18, 2018 4:53 am
x 20

Re: How to add a transparent material on top of a submesh

Post by cc9cii »

Just saw your edit :D

Post Reply