Transparent shadows issue

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Nickak2003
Goblin
Posts: 272
Joined: Thu Jun 10, 2004 4:19 am
x 26

Transparent shadows issue

Post by Nickak2003 »

I am trying to get transparent shadows for my trees, but the following, which I found in a post, does not seem to work:

Code: Select all

    
    Ogre::HlmsPbsDatablock* dataBlock = dynamic_cast<Ogre::HlmsPbsDatablock*>(Ogre::Root::getSingleton().getHlmsManager()->getHlms(Ogre::HLMS_PBS)->getDefaultDatablock());
   
    dataBlock->setTransparency(0);
    dataBlock->setAlphaTest(Ogre::CMPF_LESS_EQUAL);
    dataBlock->setAlphaTestThreshold(0.5f);

shadows appear mesh-based and not diffuse-texure-alpha. (blocky)
I am using terra if that has to do with anything.
here's my material:

Code: Select all

hlms tree1_lod_2 pbs
{
	scene_blend	alpha_blend
	depth_write	on
	diffuse_map	tree1_lod_2_diffuse.png
	specular_map	tree1_lod_2_diffuse.png
	normal_map	tree1_lod_2_normal.png
}
Thanks!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: Transparent shadows issue

Post by dark_sylinc »

Hi!
Nickak2003 wrote: Wed Sep 23, 2020 3:12 pm

Code: Select all

    
    Ogre::HlmsPbsDatablock* dataBlock = dynamic_cast<Ogre::HlmsPbsDatablock*>(Ogre::Root::getSingleton().getHlmsManager()->getHlms(Ogre::HLMS_PBS)->getDefaultDatablock());
This is wrong. You're only changing the default datablock, which is only used when we couldn't find a valid material to apply, thus this datablock is used as fallback.

If you want to grab the proper datablock, either do:

Code: Select all

Ogre::HlmsPbsDatablock* dataBlock = static_cast<Ogre::HlmsPbsDatablock*>(getHlms(Ogre::HLMS_PBS)->getDatablock( "tree1_lod_2" ));
or (if you have the leave model):

Code: Select all

Ogre::HlmsDatablock *baseDatablock = subItem->getDatablock();
assert( dynamic_cast<Ogre::HlmsPbsDatablock *>( baseDatablock ) );
Ogre::HlmsPbsDatablock* dataBlock = 
static_cast<Ogre::HlmsPbsDatablock*>( baseDatablock );
Nickak2003 wrote: Wed Sep 23, 2020 3:12 pm

Code: Select all

    
    dataBlock->setTransparency(0);
    dataBlock->setAlphaTest(Ogre::CMPF_LESS_EQUAL);
    dataBlock->setAlphaTestThreshold(0.5f);
You're combining transparency and alpha testing; and by doing so you block transparent shadows from working. However because this code is altering the default datablock it wasn't going to work.
Nickak2003 wrote: Wed Sep 23, 2020 3:12 pm

Code: Select all

hlms tree1_lod_2 pbs
{
	scene_blend	alpha_blend
	depth_write	on
	diffuse_map	tree1_lod_2_diffuse.png
	specular_map	tree1_lod_2_diffuse.png
	normal_map	tree1_lod_2_normal.png
}
Alpha blending and depth_write don't combine well. Depth writes should be off if alpha blending is used.

Solutions:

First, the bark wood material must be separate from the leaves.

There are two main ways to render leaves:
  1. Leaves use alpha testing, shadow casters also use alpha testing. This is faster, plays very well with depth order and what most games do (recommended)
  2. Leaves use alpha blending, shadow casters use alpha testing. This is slower but the leaves during render are softer (look better antialiased) but if leaves get rendered out of order (very difficult to control) it's going to look wrong. This is difficult to fix and hence it's rarely used in games.
To achieve the first one, just do:

Code: Select all

hlms tree1_lod_2 pbs
{
	// Alternatively, 'alpha_test greater 0.5'
	alpha_test less 0.5
	diffuse_map	tree1_lod_2_diffuse.png
	specular_map	tree1_lod_2_diffuse.png
	normal_map	tree1_lod_2_normal.png
}
0.5 is an arbitrary threshold. You may tweak that value.

To achieve the second, just do:

Code: Select all

hlms tree1_lod_2 pbs
{
        alpha_from_textures true
	// Alternatively, 'alpha_test greater 0.5 true'
	alpha_test less 0.5 true
	diffuse_map	tree1_lod_2_diffuse.png
	specular_map	tree1_lod_2_diffuse.png
	normal_map	tree1_lod_2_normal.png
}
That's it.

Cheers
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: Transparent shadows issue

Post by dark_sylinc »

Hi!
Nickak2003 wrote: Wed Sep 23, 2020 3:12 pm

Code: Select all

    
    Ogre::HlmsPbsDatablock* dataBlock = dynamic_cast<Ogre::HlmsPbsDatablock*>(Ogre::Root::getSingleton().getHlmsManager()->getHlms(Ogre::HLMS_PBS)->getDefaultDatablock());
This is wrong. You're only changing the default datablock, which is only used when we couldn't find a valid material to apply, thus this datablock is used as fallback.

If you want to grab the proper datablock, either do:

Code: Select all

Ogre::HlmsPbsDatablock* dataBlock = static_cast<Ogre::HlmsPbsDatablock*>(getHlms(Ogre::HLMS_PBS)->getDatablock( "tree1_lod_2" ));
or (if you have the leave model):

Code: Select all

Ogre::HlmsDatablock *baseDatablock = subItem->getDatablock();
assert( dynamic_cast<Ogre::HlmsPbsDatablock *>( baseDatablock ) );
Ogre::HlmsPbsDatablock* dataBlock = 
static_cast<Ogre::HlmsPbsDatablock*>( baseDatablock );
Nickak2003 wrote: Wed Sep 23, 2020 3:12 pm

Code: Select all

    
    dataBlock->setTransparency(0);
    dataBlock->setAlphaTest(Ogre::CMPF_LESS_EQUAL);
    dataBlock->setAlphaTestThreshold(0.5f);
You're combining transparency and alpha testing; and by doing so you block transparent shadows from working. However because this code is altering the default datablock it wasn't going to work.
Nickak2003 wrote: Wed Sep 23, 2020 3:12 pm

Code: Select all

hlms tree1_lod_2 pbs
{
	scene_blend	alpha_blend
	depth_write	on
	diffuse_map	tree1_lod_2_diffuse.png
	specular_map	tree1_lod_2_diffuse.png
	normal_map	tree1_lod_2_normal.png
}
Alpha blending and depth_write don't combine well. Depth writes should be off if alpha blending is used.

Solutions:

First, the bark wood material must be separate from the leaves.

There are two main ways to render leaves:
  1. Leaves use alpha testing, shadow casters also use alpha testing. This is faster, plays very well with depth order and what most games do (recommended)
  2. Leaves use alpha blending, shadow casters use alpha testing. This is slower but the leaves during render are softer (look better antialiased) but if leaves get rendered out of order (very difficult to control) it's going to look wrong. This is difficult to fix and hence it's rarely used in games.
To achieve the first one, just do:

Code: Select all

hlms tree1_lod_2 pbs
{
	// Alternatively, 'alpha_test greater 0.5'
	alpha_test less 0.5
	diffuse_map	tree1_lod_2_diffuse.png
	specular_map	tree1_lod_2_diffuse.png
	normal_map	tree1_lod_2_normal.png
}
0.5 is an arbitrary threshold. You may tweak that value.

Although you can alpha testing on both the bark wood and the leaf materials; using it on bark wood is going to waste a lot of GPU performance; which is why you should separate the two into different materials.

To achieve the second method, just do:

Code: Select all

hlms tree1_lod_2 pbs
{
        alpha_from_textures true
	// Alternatively, 'alpha_test greater 0.5 true'
	alpha_test less 0.5 true
	diffuse_map	tree1_lod_2_diffuse.png
	specular_map	tree1_lod_2_diffuse.png
	normal_map	tree1_lod_2_normal.png
}
That's it.

Cheers
Nickak2003
Goblin
Posts: 272
Joined: Thu Jun 10, 2004 4:19 am
x 26

Re: Transparent shadows issue

Post by Nickak2003 »

Is there a way to get shadows if alpha-blending is enabled, and depth-writes is off? Basically, what I've done so far is create an lod system where I blend one lod with the other lod over a brief period to avoid popping to some extent, and it also creates a neat "feature" effect. I would kind of like to keep this around, but without depth-write-on, I don't get shadows. I do see some oddity with depth-write-on and alpha-blend, which I would like to resolve. I am yet to implement your suggested changes for the leaf shadows, though I will investigate doing so.

Thanks
Nickak2003
Goblin
Posts: 272
Joined: Thu Jun 10, 2004 4:19 am
x 26

Re: Transparent shadows issue

Post by Nickak2003 »

Or rather, I think i need depth-write-on to some extent, how can I resolve alpha-blend an depth-write-on issues?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: Transparent shadows issue

Post by dark_sylinc »

Nickak2003 wrote: Fri Sep 25, 2020 5:46 pm Is there a way to get shadows if alpha-blending is enabled, and depth-writes is off? Basically, what I've done so far is create an lod system where I blend one lod with the other lod over a brief period to avoid popping to some extent, and it also creates a neat "feature" effect. I would kind of like to keep this around, but without depth-write-on, I don't get shadows.
Yes. I'm not sure if it can be done via script materials (it can be done with JSON materials and C++). You need to set alpha test only to the shadow caster, and set a custom macroblock on the shadow caster.

This needs to be done last, because normal calls will usually override your changes to the caster passes:

Code: Select all

datablock->setAlphaTest( CMPF_LESS, 0.5f, true );
datablock->setBlendblock( HlmsBlendblock(), true ); // Disable alpha blending on the shadow casting pass
datablock->setMacroblock( HlmsMacroblock(), true ); // Use a default macroblock on the shadow casting pass
Nickak2003 wrote: Fri Sep 25, 2020 5:47 pm Or rather, I think i need depth-write-on to some extent, how can I resolve alpha-blend an depth-write-on issues?
That is a very advanced topic. It needs an OIT solution (Order Independent Transparency); such as per-pixel linked lists (PDF1, PDF2) or approximation hacks such as Weighted Blended OIT, or depth peeling.

Ogre can be extended to implement these algorithms, but we don't provide them out of the box.
Note that with the exception of WBOIT (which is an approximation), OIT solutions tend to be quite slow (i.e. they run at 20-100 fps at 1080p with 200 transparent objects; very good for CAD solutions like car engine or other engineering visualizations, very bad for games and most other applications)