ParallaxMappingExampleComponent.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <ParallaxMappingExampleComponent.h>
  9. #include <Atom/Component/DebugCamera/ArcBallControllerComponent.h>
  10. #include <Atom/RPI.Public/RPISystemInterface.h>
  11. #include <Atom/RPI.Public/Scene.h>
  12. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  13. #include <Automation/ScriptableImGui.h>
  14. #include <AzCore/Component/TransformBus.h>
  15. #include <RHI/BasicRHIComponent.h>
  16. namespace AtomSampleViewer
  17. {
  18. static const char* ParallaxEnableName = "parallax.useTexture";
  19. static const char* PdoEnableName = "parallax.pdo";
  20. static const char* ParallaxFactorName = "parallax.factor";
  21. static const char* ParallaxHeightOffsetName = "parallax.offset";
  22. static const char* ParallaxShowClippingName = "parallax.showClipping";
  23. static const char* ParallaxAlgorithmName = "parallax.algorithm";
  24. static const char* ParallaxQualityName = "parallax.quality";
  25. static const char* ParallaxUvIndexName = "parallax.textureMapUv";
  26. static const char* AmbientOcclusionUvIndexName = "occlusion.diffuseTextureMapUv";
  27. static const char* BaseColorUvIndexName = "baseColor.textureMapUv";
  28. static const char* NormalUvIndexName = "normal.textureMapUv";
  29. static const char* RoughnessUvIndexName = "roughness.textureMapUv";
  30. static const char* CenterUVName = "uv.center";
  31. static const char* TileUName = "uv.tileU";
  32. static const char* TileVName = "uv.tileV";
  33. static const char* OffsetUName = "uv.offsetU";
  34. static const char* OffsetVName = "uv.offsetV";
  35. static const char* RotationUVName = "uv.rotateDegrees";
  36. static const char* ScaleUVName = "uv.scale";
  37. // Must align with enum value in StandardPbr.materialtype
  38. static const char* ParallaxAlgorithmList[] =
  39. {
  40. "Basic", "Steep", "POM", "Relief", "ContactRefinement"
  41. };
  42. static const char* ParallaxQualityList[] =
  43. {
  44. "Low", "Medium", "High", "Ultra"
  45. };
  46. static const char* ParallaxUvSetList[] =
  47. {
  48. "UV0", "UV1"
  49. };
  50. void ParallaxMappingExampleComponent::Reflect(AZ::ReflectContext* context)
  51. {
  52. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  53. {
  54. serializeContext->Class < ParallaxMappingExampleComponent, AZ::Component>()->Version(0);
  55. }
  56. }
  57. ParallaxMappingExampleComponent::ParallaxMappingExampleComponent()
  58. : m_imguiSidebar("@user@/ParallaxMappingExampleComponent/sidebar.xml")
  59. {
  60. }
  61. void ParallaxMappingExampleComponent::Activate()
  62. {
  63. // Asset
  64. m_planeAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/plane.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
  65. m_boxAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::ModelAsset>("objects/cube.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert);
  66. m_parallaxMaterialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>("testdata/materials/parallaxrock.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert);
  67. m_defaultMaterialAsset = AZ::RPI::AssetUtils::GetAssetByProductPath<AZ::RPI::MaterialAsset>("materials/defaultpbr.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert);
  68. m_parallaxMaterial = AZ::RPI::Material::Create(m_parallaxMaterialAsset);
  69. m_defaultMaterial = AZ::RPI::Material::Create(m_defaultMaterialAsset);
  70. m_planeTransform = AZ::Transform::CreateUniformScale(5);
  71. m_planeHandle = LoadMesh(m_planeAsset, m_parallaxMaterial, m_planeTransform);
  72. m_boxHandle = LoadMesh(m_boxAsset, m_defaultMaterial, AZ::Transform::CreateIdentity());
  73. // Material index
  74. m_parallaxEnableIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxEnableName));
  75. m_parallaxFactorIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxFactorName));
  76. m_parallaxOffsetIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxHeightOffsetName));
  77. m_parallaxShowClippingIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxShowClippingName));
  78. m_parallaxAlgorithmIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxAlgorithmName));
  79. m_parallaxQualityIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxQualityName));
  80. m_parallaxUvIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ParallaxUvIndexName));
  81. m_pdoEnableIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(PdoEnableName));
  82. m_ambientOcclusionUvIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(AmbientOcclusionUvIndexName));
  83. m_baseColorUvIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(BaseColorUvIndexName));
  84. m_normalUvIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(NormalUvIndexName));
  85. m_roughnessUvIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(RoughnessUvIndexName));
  86. m_centerUVIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(CenterUVName));
  87. m_tileUIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(TileUName));
  88. m_tileVIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(TileVName));
  89. m_offsetUIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(OffsetUName));
  90. m_offsetVIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(OffsetVName));
  91. m_rotationUVIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(RotationUVName));
  92. m_scaleUVIndex = m_parallaxMaterial->FindPropertyIndex(AZ::Name(ScaleUVName));
  93. SaveCameraConfiguration();
  94. // Camera
  95. AZ::Debug::CameraControllerRequestBus::Event(
  96. GetCameraEntityId(),
  97. &AZ::Debug::CameraControllerRequestBus::Events::Enable,
  98. azrtti_typeid<AZ::Debug::ArcBallControllerComponent>());
  99. ConfigureCameraToLookDown();
  100. SetCameraConfiguration();
  101. // Light
  102. AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get();
  103. m_directionalLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::DirectionalLightFeatureProcessorInterface>();
  104. CreateDirectionalLight();
  105. m_diskLightFeatureProcessor = scene->GetFeatureProcessor<AZ::Render::DiskLightFeatureProcessorInterface>();
  106. CreateDiskLight();
  107. m_imguiSidebar.Activate();
  108. AZ::TickBus::Handler::BusConnect();
  109. }
  110. void ParallaxMappingExampleComponent::Deactivate()
  111. {
  112. GetMeshFeatureProcessor()->ReleaseMesh(m_planeHandle);
  113. GetMeshFeatureProcessor()->ReleaseMesh(m_boxHandle);
  114. RestoreCameraConfiguration();
  115. AZ::Debug::CameraControllerRequestBus::Event(
  116. GetCameraEntityId(),
  117. &AZ::Debug::CameraControllerRequestBus::Events::Disable);
  118. m_directionalLightFeatureProcessor->ReleaseLight(m_directionalLightHandle);
  119. m_diskLightFeatureProcessor->ReleaseLight(m_diskLightHandle);
  120. m_imguiSidebar.Deactivate();
  121. AZ::TickBus::Handler::BusDisconnect();
  122. }
  123. void ParallaxMappingExampleComponent::ConfigureCameraToLookDown()
  124. {
  125. const float CameraDistance = 5.0f;
  126. const float CameraPitch = -0.8f;
  127. AZ::Debug::ArcBallControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetPitch, CameraPitch);
  128. AZ::Debug::ArcBallControllerRequestBus::Event(GetCameraEntityId(), &AZ::Debug::ArcBallControllerRequestBus::Events::SetDistance, CameraDistance);
  129. }
  130. AZ::Render::MeshFeatureProcessorInterface::MeshHandle ParallaxMappingExampleComponent::LoadMesh(
  131. AZ::Data::Asset<AZ::RPI::ModelAsset> modelAsset,
  132. AZ::Data::Instance<AZ::RPI::Material> material,
  133. AZ::Transform transform)
  134. {
  135. AZ::Render::MeshFeatureProcessorInterface::MeshHandle meshHandle = GetMeshFeatureProcessor()->AcquireMesh(AZ::Render::MeshHandleDescriptor{ modelAsset }, material);
  136. GetMeshFeatureProcessor()->SetTransform(meshHandle, transform);
  137. return meshHandle;
  138. }
  139. void ParallaxMappingExampleComponent::CreateDirectionalLight()
  140. {
  141. const AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle handle = m_directionalLightFeatureProcessor->AcquireLight();
  142. m_directionalLightFeatureProcessor->SetShadowmapSize(handle, AZ::Render::ShadowmapSize::Size2048);
  143. m_directionalLightFeatureProcessor->SetCascadeCount(handle, 4);
  144. m_directionalLightFeatureProcessor->SetShadowmapFrustumSplitSchemeRatio(handle, 0.5f);
  145. m_directionalLightFeatureProcessor->SetViewFrustumCorrectionEnabled(handle, true);
  146. m_directionalLightFeatureProcessor->SetShadowFilterMethod(handle, AZ::Render::ShadowFilterMethod::Esm);
  147. m_directionalLightFeatureProcessor->SetShadowBoundaryWidth(handle, 0.03f);
  148. m_directionalLightFeatureProcessor->SetPredictionSampleCount(handle, 8);
  149. m_directionalLightFeatureProcessor->SetFilteringSampleCount(handle, 32);
  150. m_directionalLightFeatureProcessor->SetGroundHeight(handle, 0.f);
  151. m_directionalLightHandle = handle;
  152. }
  153. void ParallaxMappingExampleComponent::CreateDiskLight()
  154. {
  155. AZ::Render::DiskLightFeatureProcessorInterface* const featureProcessor = m_diskLightFeatureProcessor;
  156. const AZ::Render::DiskLightFeatureProcessorInterface::LightHandle handle = featureProcessor->AcquireLight();
  157. featureProcessor->SetAttenuationRadius(handle, sqrtf(500.f / CutoffIntensity));
  158. featureProcessor->SetConeAngles(handle, AZ::DegToRad(22.5f) * ConeAngleInnerRatio, AZ::DegToRad(22.5f));
  159. featureProcessor->SetShadowsEnabled(handle, true);
  160. featureProcessor->SetShadowmapMaxResolution(handle, AZ::Render::ShadowmapSize::Size2048);
  161. m_diskLightHandle = handle;
  162. }
  163. void ParallaxMappingExampleComponent::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
  164. {
  165. if (m_lightAutoRotate)
  166. {
  167. m_lightRotationAngle = fmodf(m_lightRotationAngle + deltaTime, AZ::Constants::TwoPi);
  168. }
  169. const auto location = AZ::Vector3(
  170. 5 * sinf(m_lightRotationAngle),
  171. 5 * cosf(m_lightRotationAngle),
  172. 5);
  173. auto transform = AZ::Transform::CreateLookAt(
  174. location,
  175. AZ::Vector3::CreateZero());
  176. if (m_lightType)
  177. {
  178. AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Lux> directionalLightColor(AZ::Color::CreateZero());
  179. AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> diskLightColor(AZ::Color::CreateOne() * 500.f);
  180. m_directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, directionalLightColor);
  181. m_diskLightFeatureProcessor->SetRgbIntensity(m_diskLightHandle, diskLightColor);
  182. }
  183. else
  184. {
  185. AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Lux> directionalLightColor(AZ::Color::CreateOne() * 5.f);
  186. AZ::Render::PhotometricColor<AZ::Render::PhotometricUnit::Candela> diskLightColor(AZ::Color::CreateZero());
  187. m_directionalLightFeatureProcessor->SetRgbIntensity(m_directionalLightHandle, directionalLightColor);
  188. m_diskLightFeatureProcessor->SetRgbIntensity(m_diskLightHandle, diskLightColor);
  189. }
  190. m_diskLightFeatureProcessor->SetPosition(m_diskLightHandle, location);
  191. m_diskLightFeatureProcessor->SetDirection(m_diskLightHandle, transform.GetBasis(1));
  192. m_directionalLightFeatureProcessor->SetDirection(m_directionalLightHandle, transform.GetBasis(1));
  193. // Camera Configuration
  194. {
  195. Camera::Configuration config;
  196. Camera::CameraRequestBus::EventResult(
  197. config,
  198. GetCameraEntityId(),
  199. &Camera::CameraRequestBus::Events::GetCameraConfiguration);
  200. m_directionalLightFeatureProcessor->SetCameraConfiguration(
  201. m_directionalLightHandle,
  202. config);
  203. }
  204. // Camera Transform
  205. {
  206. transform = AZ::Transform::CreateIdentity();
  207. AZ::TransformBus::EventResult(
  208. transform,
  209. GetCameraEntityId(),
  210. &AZ::TransformBus::Events::GetWorldTM);
  211. m_directionalLightFeatureProcessor->SetCameraTransform(
  212. m_directionalLightHandle, transform);
  213. }
  214. // Plane Transform
  215. {
  216. m_planeTransform.SetRotation(AZ::Quaternion::CreateRotationZ(m_planeRotationAngle));
  217. GetMeshFeatureProcessor()->SetTransform(m_planeHandle, m_planeTransform);
  218. }
  219. DrawSidebar();
  220. }
  221. void ParallaxMappingExampleComponent::SetCameraConfiguration()
  222. {
  223. Camera::CameraRequestBus::Event(
  224. GetCameraEntityId(),
  225. &Camera::CameraRequestBus::Events::SetFarClipDistance,
  226. 20.f);
  227. Camera::CameraRequestBus::Event(
  228. GetCameraEntityId(),
  229. &Camera::CameraRequestBus::Events::SetFovRadians,
  230. AZ::Constants::QuarterPi);
  231. }
  232. void ParallaxMappingExampleComponent::SaveCameraConfiguration()
  233. {
  234. Camera::CameraRequestBus::EventResult(
  235. m_originalFarClipDistance,
  236. GetCameraEntityId(),
  237. &Camera::CameraRequestBus::Events::GetFarClipDistance);
  238. Camera::CameraRequestBus::EventResult(
  239. m_originalCameraFovRadians,
  240. GetCameraEntityId(),
  241. &Camera::CameraRequestBus::Events::GetFovRadians);
  242. }
  243. void ParallaxMappingExampleComponent::RestoreCameraConfiguration()
  244. {
  245. Camera::CameraRequestBus::Event(
  246. GetCameraEntityId(),
  247. &Camera::CameraRequestBus::Events::SetFarClipDistance,
  248. m_originalFarClipDistance);
  249. Camera::CameraRequestBus::Event(
  250. GetCameraEntityId(),
  251. &Camera::CameraRequestBus::Events::SetFovRadians,
  252. m_originalCameraFovRadians);
  253. }
  254. void ParallaxMappingExampleComponent::DrawSidebar()
  255. {
  256. if (m_imguiSidebar.Begin())
  257. {
  258. bool parallaxSettingChanged = false;
  259. bool planeUVChanged = false;
  260. ImGui::Spacing();
  261. {
  262. ScriptableImGui::ScopedNameContext context{ "Lighting" };
  263. ImGui::Text("Lighting");
  264. ImGui::Indent();
  265. {
  266. ScriptableImGui::RadioButton("Directional Light", &m_lightType, 0);
  267. ScriptableImGui::RadioButton("Spot Light", &m_lightType, 1);
  268. ScriptableImGui::Checkbox("Auto Rotation", &m_lightAutoRotate);
  269. ScriptableImGui::SliderAngle("Direction", &m_lightRotationAngle, 0, 360);
  270. }
  271. ImGui::Unindent();
  272. }
  273. ImGui::Separator();
  274. {
  275. ScriptableImGui::ScopedNameContext context{ "Parallax Setting" };
  276. ImGui::Text("Parallax Setting");
  277. ImGui::Indent();
  278. {
  279. if (ScriptableImGui::Checkbox("Enable Parallax", &m_parallaxEnable))
  280. {
  281. parallaxSettingChanged = true;
  282. m_parallaxMaterial->SetPropertyValue(m_parallaxEnableIndex, m_parallaxEnable);
  283. }
  284. if (m_parallaxEnable)
  285. {
  286. if (ScriptableImGui::Checkbox("Enable Pdo", &m_pdoEnable))
  287. {
  288. parallaxSettingChanged = true;
  289. m_parallaxMaterial->SetPropertyValue(m_pdoEnableIndex, m_pdoEnable);
  290. }
  291. if (ScriptableImGui::SliderFloat("Heightmap Scale", &m_parallaxFactor, 0.0f, 0.1f))
  292. {
  293. parallaxSettingChanged = true;
  294. m_parallaxMaterial->SetPropertyValue(m_parallaxFactorIndex, m_parallaxFactor);
  295. }
  296. if (ScriptableImGui::SliderFloat("Offset", &m_parallaxOffset, -0.1f, 0.1f))
  297. {
  298. parallaxSettingChanged = true;
  299. m_parallaxMaterial->SetPropertyValue(m_parallaxOffsetIndex, m_parallaxOffset);
  300. }
  301. if (ScriptableImGui::Checkbox("Show Clipping", &m_parallaxShowClipping))
  302. {
  303. parallaxSettingChanged = true;
  304. m_parallaxMaterial->SetPropertyValue(m_parallaxShowClippingIndex, m_parallaxShowClipping);
  305. }
  306. if (ScriptableImGui::Combo("Algorithm", &m_parallaxAlgorithm, ParallaxAlgorithmList, AZ_ARRAY_SIZE(ParallaxAlgorithmList)))
  307. {
  308. parallaxSettingChanged = true;
  309. m_parallaxMaterial->SetPropertyValue(m_parallaxAlgorithmIndex, static_cast<uint32_t>(m_parallaxAlgorithm));
  310. }
  311. if (ScriptableImGui::Combo("Quality", &m_parallaxQuality, ParallaxQualityList, AZ_ARRAY_SIZE(ParallaxQualityList)))
  312. {
  313. parallaxSettingChanged = true;
  314. m_parallaxMaterial->SetPropertyValue(m_parallaxQualityIndex, static_cast<uint32_t>(m_parallaxQuality));
  315. }
  316. if (ScriptableImGui::Combo("UV", &m_parallaxUv, ParallaxUvSetList, AZ_ARRAY_SIZE(ParallaxUvSetList)))
  317. {
  318. parallaxSettingChanged = true;
  319. m_parallaxMaterial->SetPropertyValue(m_parallaxUvIndex, static_cast<uint32_t>(m_parallaxUv));
  320. m_parallaxMaterial->SetPropertyValue(m_ambientOcclusionUvIndex, static_cast<uint32_t>(m_parallaxUv));
  321. m_parallaxMaterial->SetPropertyValue(m_baseColorUvIndex, static_cast<uint32_t>(m_parallaxUv));
  322. m_parallaxMaterial->SetPropertyValue(m_normalUvIndex, static_cast<uint32_t>(m_parallaxUv));
  323. m_parallaxMaterial->SetPropertyValue(m_roughnessUvIndex, static_cast<uint32_t>(m_parallaxUv));
  324. }
  325. }
  326. }
  327. ImGui::Unindent();
  328. }
  329. ImGui::Separator();
  330. {
  331. ScriptableImGui::ScopedNameContext context{ "Plane Setting" };
  332. ImGui::Text("Plane Setting");
  333. ImGui::Indent();
  334. {
  335. ScriptableImGui::SliderAngle("Rotation", &m_planeRotationAngle, 0, 360);
  336. bool centerUChanged = false;
  337. bool centerVChanged = false;
  338. bool tileUChanged = false;
  339. bool tileVChanged = false;
  340. bool offsetUChanged = false;
  341. bool offsetVChanged = false;
  342. bool rotationUVChanged = false;
  343. bool scaleChanged = false;
  344. centerUChanged = ScriptableImGui::SliderFloat("Center U", &m_planeCenterU, -1.f, 1.f);
  345. centerVChanged = ScriptableImGui::SliderFloat("Center V", &m_planeCenterV, -1.f, 1.f);
  346. if (centerUChanged || centerVChanged)
  347. {
  348. m_parallaxMaterial->SetPropertyValue(m_centerUVIndex, AZ::Vector2(m_planeCenterU, m_planeCenterV));
  349. }
  350. tileUChanged = ScriptableImGui::SliderFloat("Tile U", &m_planeTileU, 0.f, 2.f);
  351. if (tileUChanged)
  352. {
  353. m_parallaxMaterial->SetPropertyValue(m_tileUIndex, m_planeTileU);
  354. }
  355. tileVChanged = ScriptableImGui::SliderFloat("Tile V", &m_planeTileV, 0.f, 2.f);
  356. if (tileVChanged)
  357. {
  358. m_parallaxMaterial->SetPropertyValue(m_tileVIndex, m_planeTileV);
  359. }
  360. offsetUChanged = ScriptableImGui::SliderFloat("Offset U", &m_planeOffsetU, -1.f, 1.f);
  361. if (offsetUChanged)
  362. {
  363. m_parallaxMaterial->SetPropertyValue(m_offsetUIndex, m_planeOffsetU);
  364. }
  365. offsetVChanged = ScriptableImGui::SliderFloat("Offset V", &m_planeOffsetV, -1.f, 1.f);
  366. if (offsetVChanged)
  367. {
  368. m_parallaxMaterial->SetPropertyValue(m_offsetVIndex, m_planeOffsetV);
  369. }
  370. rotationUVChanged = ScriptableImGui::SliderFloat("Rotation UV", &m_planeRotateUV, -180.f, 180.f);
  371. if (rotationUVChanged)
  372. {
  373. m_parallaxMaterial->SetPropertyValue(m_rotationUVIndex, m_planeRotateUV);
  374. }
  375. scaleChanged = ScriptableImGui::SliderFloat("Scale UV", &m_planeScaleUV, 0.f, 2.f);
  376. if (scaleChanged)
  377. {
  378. m_parallaxMaterial->SetPropertyValue(m_scaleUVIndex, m_planeScaleUV);
  379. }
  380. planeUVChanged = centerUChanged || centerVChanged || tileUChanged || tileVChanged || offsetUChanged || offsetVChanged || rotationUVChanged || scaleChanged;
  381. }
  382. ImGui::Unindent();
  383. }
  384. m_imguiSidebar.End();
  385. if (parallaxSettingChanged || planeUVChanged)
  386. {
  387. m_parallaxMaterial->Compile();
  388. }
  389. }
  390. }
  391. }