dark_sylinc wrote: ↑Tue Jun 25, 2024 3:21 pm
Hi!
Are you running in Debug mode? Because by default we use 32-bit hashes for datablock names, which can cause collisions (they usually appear at around 10.000 datablocks but it can happen sooner).
Debug mode will assert if collisions appear, but Release mode will just ignore them and cause bugs like these.
If collisions are indeed the issue, you can build OgreNext with CMake option OGRE_IDSTRING_USE_128
turned on to quickly fix it. This will make OgreNext to use 128-bit hashes instead of 32.
If this is not the problem, then I'll ask you if you can create a small repro by modifying one of the samples and upload the diff here so I can take a look. Thanks!
Hey!
Yes, I was running in debug mode - and I had already preemptively enabled the 128-bit ID string hashes, as it just made sense to me to have it (and by extension my own engine) able to handle more materials and such. I never ran into any assertions, either.
In either case, I was able to modify the decals sample (as that's the one I happened to be tinkering with to begin with before), and simply generating 900 datablocks results in the same issue happening. The only file I changed was DecalsGameState.cpp, however I did also need to add the Unlit HLMS includes to the Visual Studio project settings.
At the top of the file, I added these includes and 3 plain functions:
Code: Select all
#include "OgreHlmsUnlitDatablock.h"
#include "OgreManualObject2.h"
#include <random>
std::string random_int_string()
{
std::random_device random_device;
std::mt19937_64 generator( random_device() );
std::uniform_int_distribution<uint64_t> distribution( std::numeric_limits<std::uint64_t>::min(),
std::numeric_limits<std::uint64_t>::max() );
return std::to_string( distribution( generator ) );
}
Ogre::HlmsUnlitDatablock *create_test_unlit_datablock( Demo::GraphicsSystem *mGraphicsSystem )
{
Ogre::HlmsManager *hlmsManager = mGraphicsSystem->getRoot()->getHlmsManager();
Ogre::Hlms *hlmsUnlit = hlmsManager->getHlms( Ogre::HLMS_UNLIT );
Ogre::HlmsMacroblock macroblock = Ogre::HlmsMacroblock();
Ogre::HlmsBlendblock blendblock = Ogre::HlmsBlendblock();
blendblock.setBlendType( Ogre::SceneBlendType::SBT_TRANSPARENT_ALPHA );
Ogre::HlmsParamVec paramvec = Ogre::HlmsParamVec();
std::string datablock_id = random_int_string();
Ogre::HlmsUnlitDatablock *new_datablock = (Ogre::HlmsUnlitDatablock *)hlmsUnlit->createDatablock(
datablock_id, datablock_id, macroblock, blendblock, paramvec, true );
new_datablock->setUseColour( true );
new_datablock->setAlphaTest( Ogre::CompareFunction::CMPF_EQUAL );
return new_datablock;
}
void unlit_testing(Demo::GraphicsSystem* mGraphicsSystem)
{
for (int i = 0; i < 900; i++)
{
create_test_unlit_datablock( mGraphicsSystem );
}
Ogre::SceneManager *sceneManager = mGraphicsSystem->getSceneManager();
Ogre::ManualObject *manual_object = sceneManager->createManualObject();
Ogre::HlmsUnlitDatablock *datablock = create_test_unlit_datablock( mGraphicsSystem );
datablock->setColour(Ogre::ColourValue(1.0, 0.0, 0.0, 1));
{
manual_object->begin( *datablock->getNameStr(), Ogre::OperationType::OT_TRIANGLE_LIST );
manual_object->position( -1.0f, 1.0f, 1.0f );
manual_object->position( 1.0f, 1.0f, 1.0f );
manual_object->position( -1.0f, 1.0f, -1.0f );
manual_object->position( 1.0f, 1.0f, -1.0f );
manual_object->position( -1.0f, -1.0f, 1.0f );
manual_object->position( 1.0f, -1.0f, 1.0f );
manual_object->position( -1.0f, -1.0f, -1.0f );
manual_object->position( 1.0f, -1.0f, -1.0f );
manual_object->triangle( 0, 1, 2 );
manual_object->triangle( 1, 3, 2 );
manual_object->triangle( 4, 6, 5 );
manual_object->triangle( 5, 6, 7 );
manual_object->triangle( 0, 2, 4 );
manual_object->triangle( 4, 2, 6 );
manual_object->triangle( 1, 5, 3 );
manual_object->triangle( 5, 7, 3 );
manual_object->triangle( 0, 4, 1 );
manual_object->triangle( 4, 5, 1 );
manual_object->triangle( 2, 3, 6 );
manual_object->triangle( 6, 3, 7 );
manual_object->end();
}
Ogre::SceneNode *sceneNode = sceneManager->createSceneNode(Ogre::SCENE_DYNAMIC );
sceneNode->attachObject( manual_object );
sceneNode->setPosition( 0, 20, 0 );
}
The only other change made to the file was calling unlit_testing
near the end of DecalsGameState::createScene01
, right before the call to TutorialGameState::createScene01();
:
Code: Select all
void DecalsGameState::createScene01()
{
// ...
Ogre::uint32 visibilityMask = mGraphicsSystem->getSceneManager()->getVisibilityMask();
visibilityMask &= ~0x00000002u;
visibilityMask &= ~0x00000001u;
mGraphicsSystem->getSceneManager()->setVisibilityMask( visibilityMask );
unlit_testing( mGraphicsSystem );
TutorialGameState::createScene01();
}
Later
There will be a new unlit cube above the main area (a bit high up), generated using a ManualObject in the unlit_testing
function.
By default, the cube will appear white - when it should instead be red. Commenting out the for loop at the start of unlit_testing
will skip generating the 900 datablocks, and the cube will be red. Haven't directly checked memory or anything like that, but seems to be pretty clearly the same issue.