diff --git a/examples/projector/Main.cc b/examples/projector/Main.cc index c19f00d18..9d2d7b199 100644 --- a/examples/projector/Main.cc +++ b/examples/projector/Main.cc @@ -30,6 +30,8 @@ #include #include +#include + #include "example_config.hh" #include "GlutWindow.hh" @@ -142,6 +144,51 @@ void buildScene(ScenePtr _scene) camera->SetVisibilityMask(0x01); root->AddChild(camera); + + auto data = std::make_shared(); + data->Load(common::joinPaths(RESOURCE_PATH, "heightmap_bowl.png")); + + HeightmapDescriptor desc; + desc.SetName("example_bowl"); + desc.SetData(data); + desc.SetSize({17, 17, 10}); + desc.SetSampling(2u); + desc.SetUseTerrainPaging(false); + + HeightmapTexture textureA; + textureA.SetSize(1.0); + textureA.SetDiffuse("../media/dirt_diffusespecular.png"); + textureA.SetNormal("../media/flat_normal.png"); + desc.AddTexture(textureA); + + HeightmapBlend blendA; + blendA.SetMinHeight(2.0); + blendA.SetFadeDistance(5.0); + desc.AddBlend(blendA); + + HeightmapTexture textureB; + textureB.SetSize(1.0); + textureB.SetDiffuse("../media/grass_diffusespecular.png"); + textureB.SetNormal("../media/flat_normal.png"); + desc.AddTexture(textureB); + + HeightmapBlend blendB; + blendB.SetMinHeight(4.0); + blendB.SetFadeDistance(5.0); + desc.AddBlend(blendB); + + HeightmapTexture textureC; + textureC.SetSize(1.0); + textureC.SetDiffuse("../media/fungus_diffusespecular.png"); + textureC.SetNormal("../media/flat_normal.png"); + desc.SetPosition({-20, 10, 0}); + desc.AddTexture(textureC); + + auto heightmapGeom = _scene->CreateHeightmap(desc); + + auto vis = _scene->CreateVisual(); + vis->AddGeometry(heightmapGeom); + root->AddChild(vis); } ////////////////////////////////////////////////// diff --git a/ogre2/src/Ogre2Heightmap.cc b/ogre2/src/Ogre2Heightmap.cc index fadd8a315..c303ddea5 100644 --- a/ogre2/src/Ogre2Heightmap.cc +++ b/ogre2/src/Ogre2Heightmap.cc @@ -260,6 +260,9 @@ void Ogre2Heightmap::Init() Ogre::Hlms *hlmsTerra = ogreRoot->getHlmsManager()->getHlms(Ogre::HLMS_USER3); + hlmsTerra->setDebugOutputPath(true, false); + // hlmsTerra->_setProperty(Ogre::HlmsBaseProp::EnableDecals, 0); + // hlmsTerra->_setProperty(Ogre::HlmsBaseProp::DecalsDiffuse, 1); GZ_ASSERT(dynamic_cast(hlmsTerra), "HlmsTerra incorrectly setup, memory corrupted, or " diff --git a/ogre2/src/Ogre2Projector.cc b/ogre2/src/Ogre2Projector.cc index 1e25281e8..6052acc5d 100644 --- a/ogre2/src/Ogre2Projector.cc +++ b/ogre2/src/Ogre2Projector.cc @@ -110,15 +110,16 @@ Ogre2Projector::Ogre2Projector() ///////////////////////////////////////////////// Ogre2Projector::~Ogre2Projector() { - this->SetEnabled(false); - if (!this->scene->IsInitialized()) return; + this->SetEnabled(false); + for (const auto &ogreCamIt : this->dataPtr->camerasWithListener) { Ogre::IdString camName = ogreCamIt.second; auto ogreCam = this->scene->OgreSceneManager()->findCameraNoThrow(camName); + if (ogreCam) ogreCam->removeListener(this->dataPtr->listener.get()); } this->dataPtr->camerasWithListener.clear(); @@ -230,6 +231,7 @@ void Ogre2Projector::CreateProjector() { this->dataPtr->decalNode = this->ogreNode->createChildSceneNode(); this->dataPtr->decalNode->roll(Ogre::Degree(90)); + this->dataPtr->decalNode->yaw(Ogre::Degree(180)); this->dataPtr->decal = this->scene->OgreSceneManager()->createDecal(); this->dataPtr->decalNode->attachObject(this->dataPtr->decal); @@ -275,7 +277,8 @@ void Ogre2Projector::CreateProjector() // approximate frustum size common::Image image(this->textureName); - const double aspectRatio = image.Width() / image.Height(); + const double aspectRatio = static_cast(image.Width()) / + static_cast(image.Height()); const double vfov = 2.0 * atan(tan(this->hfov.Radian() / 2.0) / aspectRatio); diff --git a/ogre2/src/media/Hlms/Terra/GLSL/PixelShader_ps.glsl b/ogre2/src/media/Hlms/Terra/GLSL/PixelShader_ps.glsl index 3b34287df..186ec618f 100644 --- a/ogre2/src/media/Hlms/Terra/GLSL/PixelShader_ps.glsl +++ b/ogre2/src/media/Hlms/Terra/GLSL/PixelShader_ps.glsl @@ -108,7 +108,28 @@ vulkan( layout( ogre_s@value(terrainNormals) ) uniform sampler samplerStateTerra @insertpiece( DeclParallaxLocalCorrect ) @end -@insertpiece( DeclDecalsSamplers ) +// The DeclDecalsSamplers insertpiece does not seem to do anything. +// The contents from DeclDecalsSamplers are manually pasted below +// This prevents a crash when there are decals in the scene +// @insertpiece( DeclDecalsSamplers ) +@property( hlms_forwardplus ) +@property( hlms_enable_decals ) + @piece( DeclDecalsSamplers ) + @property( syntax == glslvk ) + layout( ogre_s@value(decalsSampler) ) uniform sampler decalsSampler; + @end + @property( hlms_decals_diffuse ) vulkan_layout( ogre_t@value(decalsDiffuseTex) ) uniform texture2DArray decalsDiffuseTex;@end + @property( hlms_decals_normals )vulkan_layout( ogre_t@value(decalsNormalsTex) ) uniform texture2DArray decalsNormalsTex;@end + @property( hlms_decals_diffuse == hlms_decals_emissive ) + #define decalsEmissiveTex decalsDiffuseTex + @end + @property( hlms_decals_emissive && hlms_decals_diffuse != hlms_decals_emissive ) + vulkan_layout( ogre_t@value(decalsEmissiveTex) ) uniform texture2DArray decalsEmissiveTex; + @end + @end +@end +@end + @insertpiece( DeclShadowMapMacros ) @insertpiece( DeclShadowSamplers ) diff --git a/ogre2/src/media/Hlms/Terra/gz/500.gz_Structs_piece_all.any b/ogre2/src/media/Hlms/Terra/gz/500.gz_Structs_piece_all.any index 60ca19c92..72ddbe697 100644 --- a/ogre2/src/media/Hlms/Terra/gz/500.gz_Structs_piece_all.any +++ b/ogre2/src/media/Hlms/Terra/gz/500.gz_Structs_piece_all.any @@ -8,4 +8,7 @@ @piece( custom_VStoPS_terra ) INTERPOLANT( float localHeight, @counter(texcoord) ); + + // added to prevent crash when decals are in the scene + INTERPOLANT( float3 normal, @counter(texcoord) ); @end diff --git a/test/integration/projector.cc b/test/integration/projector.cc index 134380c4f..4026c5364 100644 --- a/test/integration/projector.cc +++ b/test/integration/projector.cc @@ -20,8 +20,10 @@ #include "CommonRenderingTest.hh" #include +#include #include "gz/rendering/Camera.hh" +#include "gz/rendering/Heightmap.hh" #include "gz/rendering/Material.hh" #include "gz/rendering/Projector.hh" #include "gz/rendering/Scene.hh" @@ -47,11 +49,6 @@ TEST_F(ProjectorTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Visibility)) ScenePtr scene = engine->CreateScene("scene"); ASSERT_NE(nullptr, scene); - // Projector and can only be accessed by the scene extension API - // in gz-rendering7 - if (!scene->Extension()) - return; - scene->SetBackgroundColor(0, 0, 0); scene->SetAmbientLight(1, 1, 1); @@ -152,11 +149,9 @@ TEST_F(ProjectorTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Visibility)) common::Image imgA; imgA.SetFromData(dataA, width, height, common::Image::RGB_INT8); - imgA.SavePNG("imageA.png"); common::Image imgB; imgB.SetFromData(dataB, width, height, common::Image::RGB_INT8); - imgB.SavePNG("imageB.png"); for (unsigned int i = 0; i < height; ++i) { @@ -184,3 +179,101 @@ TEST_F(ProjectorTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Visibility)) // Clean up engine->DestroyScene(scene); } + +///////////////////////////////////////////////// +TEST_F(ProjectorTest, GZ_UTILS_TEST_DISABLED_ON_WIN32(Heightmap)) +{ + // This test checks that projectors and heightmaps can co-exist + ScenePtr scene = engine->CreateScene("scene"); + ASSERT_NE(nullptr, scene); + + scene->SetBackgroundColor(0, 0, 0); + scene->SetAmbientLight(1, 1, 1); + + VisualPtr root = scene->RootVisual(); + ASSERT_NE(nullptr, root); + + DirectionalLightPtr light0 = scene->CreateDirectionalLight(); + light0->SetDirection(0.0, 0.0, -1); + light0->SetDiffuseColor(1.0, 1.0, 1.0); + light0->SetSpecularColor(1.0, 1.0, 1.0); + root->AddChild(light0); + + CameraPtr cameraA = scene->CreateCamera(); + ASSERT_NE(nullptr, cameraA); + cameraA->SetWorldPosition(0, 0, -2); + cameraA->SetWorldRotation(0, GZ_PI / 2.0, 0); + cameraA->SetVisibilityMask(0x01); + cameraA->SetImageWidth(256); + cameraA->SetImageHeight(256); + root->AddChild(cameraA); + + // create projectors with different visibility flags + std::string textureRed = common::joinPaths( + TEST_MEDIA_PATH, "materials", "textures", + "red_texture.png"); + ProjectorPtr projectorA = scene->CreateProjector(); + ASSERT_NE(nullptr, projectorA); + projectorA->SetNearClipPlane(1.0); + projectorA->SetFarClipPlane(6.0); + projectorA->SetTexture(textureRed); + projectorA->SetVisibilityFlags(0x01); + projectorA->SetWorldRotation(0, GZ_PI / 2.0, 0); + root->AddChild(projectorA); + + // create ImageHeightmap + auto data = std::make_shared(); + data->Load(common::joinPaths(TEST_MEDIA_PATH, "heightmap_bowl.png")); + + HeightmapDescriptor desc; + desc.SetName("example_bowl"); + desc.SetData(data); + desc.SetSize({ 17, 17, 7.0 }); + desc.SetSampling(2u); + desc.SetUseTerrainPaging(false); + + const auto textureImage = + common::joinPaths(TEST_MEDIA_PATH, "materials", "textures", "texture.png"); + const auto normalImage = common::joinPaths(TEST_MEDIA_PATH, "materials", + "textures", "flat_normal.png"); + + HeightmapTexture textureA; + textureA.SetSize(1.0); + textureA.SetDiffuse(textureImage); + textureA.SetNormal(normalImage); + desc.AddTexture(textureA); + + HeightmapBlend blendA; + blendA.SetMinHeight(2.0); + blendA.SetFadeDistance(5.0); + desc.AddBlend(blendA); + + HeightmapTexture textureB; + textureB.SetSize(1.0); + textureB.SetDiffuse(textureImage); + textureB.SetNormal(normalImage); + desc.AddTexture(textureB); + + HeightmapBlend blendB; + blendB.SetMinHeight(4.0); + blendB.SetFadeDistance(5.0); + desc.AddBlend(blendB); + + HeightmapTexture textureC; + textureC.SetSize(1.0); + textureC.SetDiffuse(textureImage); + textureC.SetNormal(normalImage); + desc.AddTexture(textureC); + auto heightmapGeom = scene->CreateHeightmap(desc); + auto vis = scene->CreateVisual(); + vis->AddGeometry(heightmapGeom); + root->AddChild(vis); + + // render once to update scene graph and make sure + // there are no crashes + Image imageA = cameraA->CreateImage(); + EXPECT_NO_THROW(cameraA->Capture(imageA)); + + // Clean up + engine->DestroyScene(scene); +}