/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include "StdAfx.h" #if AZ_RENDER_TO_TEXTURE_GEM_ENABLED #include "RenderToTextureComponent.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace AzRTT { void RenderContextConfig::Reflect(AZ::ReflectContext* reflection) { AZ::SerializeContext* serializeContext = azrtti_cast(reflection); if (serializeContext) { serializeContext->Class() ->Version(1) ->Field("Width", &RenderContextConfig::m_width) ->Field("Height", &RenderContextConfig::m_height) ->Field("Enable Gamma", &RenderContextConfig::m_sRGBWrite) ->Field("Alpha Output Mode", &RenderContextConfig::m_alphaMode) ->Field("Enable Ocean", &RenderContextConfig::m_oceanEnabled) ->Field("Enable Terrain", &RenderContextConfig::m_terrainEnabled) ->Field("Enable Vegetation", &RenderContextConfig::m_vegetationEnabled) ->Field("Enable Shadows", &RenderContextConfig::m_shadowsEnabled) ->Field("GSM LODs", &RenderContextConfig::m_shadowsNumCascades) ->Field("GSM Range", &RenderContextConfig::m_shadowsGSMRange) ->Field("GSM Range Step", &RenderContextConfig::m_shadowsGSMRangeStep) ->Field("Antialiasing Mode", &RenderContextConfig::m_aaMode) ->Field("Enable Depth Of Field", &RenderContextConfig::m_depthOfFieldEnabled) ->Field("Enable Motion Blur", &RenderContextConfig::m_motionBlurEnabled) ; } } } namespace RenderToTexture { /// BahaviorContext forwarder for RenderToTextureNotificationBus class BehaviorRenderToTextureNotificationBusHandler : public RenderToTexture::RenderToTextureNotificationBus::Handler, public AZ::BehaviorEBusHandler { public: AZ_EBUS_BEHAVIOR_BINDER(BehaviorRenderToTextureNotificationBusHandler, "{8E5D1D55-317B-42FA-A8A4-AC410B671C87}", AZ::SystemAllocator, OnPreRenderToTexture, OnPostRenderToTexture); void OnPreRenderToTexture() override { Call(FN_OnPreRenderToTexture); } void OnPostRenderToTexture() override { Call(FN_OnPostRenderToTexture); } }; void RenderToTextureConfig::Reflect(AZ::ReflectContext* reflection) { AzRTT::RenderContextConfig::Reflect(reflection); AZ::SerializeContext* serializeContext = azrtti_cast(reflection); if (serializeContext) { serializeContext->Class() ->Version(1) ->Field("Enabled", &RenderToTextureConfig::m_enabled) ->Field("Camera", &RenderToTextureConfig::m_camera) ->Field("Texture Name", &RenderToTextureConfig::m_textureName) ->Field("Max FPS", &RenderToTextureConfig::m_maxFPS) ->Field("Render Context Config", &RenderToTextureConfig::m_renderContextConfig) ->Field("Display Debug Image", &RenderToTextureConfig::m_displayDebugImage); } } void RenderToTextureComponent::Reflect(AZ::ReflectContext* reflection) { RenderToTextureBase::Reflect(reflection); RenderToTextureConfig::Reflect(reflection); AZ::SerializeContext* serializeContext = azrtti_cast(reflection); if (serializeContext) { serializeContext->Class() ->Version(1) ->Field("Config", &RenderToTextureComponent::m_config); } AZ::BehaviorContext* behaviorContext = azrtti_cast(reflection); if (behaviorContext) { behaviorContext->EBus("RenderToTextureRequestBus") ->Attribute(AZ::Script::Attributes::Category, "Rendering") ->Event("GetTextureResourceId", &RenderToTextureRequestBus::Events::GetTextureResourceId) ->Event("SetCamera", &RenderToTextureRequestBus::Events::SetCamera, { { { "Camera" , "The entity ID of the camera to use for rendering" } } }) ->Event("SetEnabled", &RenderToTextureRequestBus::Events::SetEnabled, { { { "Enabled" , "Enable or disable rendering to texture" } } }) ->Event("SetMaxFPS", &RenderToTextureRequestBus::Events::SetMaxFPS, { { { "FPS" , "Limit how often the scene is re-rendered and the render target is updated" } } }) ->Event("SetWriteGamma", &RenderToTextureRequestBus::Events::SetWriteSRGBEnabled, { { { "Enabled" , "Enable or disable gamma application in the render target output." } } }) ->Event("SetAlphaMode", &RenderToTextureRequestBus::Events::SetAlphaMode, { { { "Mode" , "Set the alpha mode (0 = disabled, 1 = opaque, 2 = depth based)" } } }); behaviorContext->EBus("RenderToTextureNotificationBus") ->Attribute(AZ::Script::Attributes::Category, "Rendering") ->Handler(); } } void RenderToTextureComponent::Activate() { if (gEnv->IsDedicated()) { AZ_WarningOnce("RenderToTextureComponent", gEnv->IsDedicated(), "$2RenderToTexture is not supported in dedicated server mode."); return; } if (!m_config.m_camera.IsValid()) { m_config.m_camera = GetEntityId(); } AzRTT::RTTRequestBus::BroadcastResult(m_config.m_renderContextId, &AzRTT::RTTRequestBus::Events::CreateContext, m_config.m_renderContextConfig); if (m_config.m_renderContextId.IsNull()) { #if !defined(AZ_TESTS_ENABLED) AZ_Printf("RenderToTextureComponent", "$2Failed to create render context."); #endif // !defined(AZ_TESTS_ENABLED) } else if (gEnv->pRenderer) { m_renderTargetHandle = gEnv->pRenderer->CreateRenderTarget(m_config.m_textureName.c_str(), m_config.m_renderContextConfig.m_width, m_config.m_renderContextConfig.m_height, Clr_Unknown, eTF_R8G8B8A8); if (m_renderTargetHandle <= 0) { AZ_Printf("RenderToTextureComponent", "$2Failed to create render target."); } else if (m_config.m_enabled) { if (gEnv->IsEditorSimulationMode()) { AZ::TickBus::Handler::BusConnect(); } else if (gEnv->pGame && gEnv->pGame->GetIGameFramework()) { gEnv->pGame->GetIGameFramework()->RegisterListener(this, "RenderToTextureComponent", FRAMEWORKLISTENERPRIORITY_HUD); } #ifndef _RELEASE // validate cvar settings ValidateCVars(); #endif // ifndef _RELEASE } } RenderToTextureRequestBus::Handler::BusConnect(GetEntityId()); } void RenderToTextureComponent::Deactivate() { if (!m_config.m_renderContextId.IsNull()) { AzRTT::RTTRequestBus::Broadcast(&AzRTT::RTTRequestBus::Events::DestroyContext, m_config.m_renderContextId); } if (m_renderTargetHandle >= 0) { if (gEnv->pRenderer) { gEnv->pRenderer->DestroyRenderTarget(m_renderTargetHandle); } m_renderTargetHandle = -1; } if (gEnv->pGame && gEnv->pGame->GetIGameFramework()) { gEnv->pGame->GetIGameFramework()->UnregisterListener(this); } RenderToTextureRequestBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); } int RenderToTextureComponent::GetTickOrder() { return AZ::TICK_LAST; } void RenderToTextureComponent::OnTick(float deltaTime, AZ::ScriptTimePoint time) { // we only connect to the tickbus for simulation mode in the editor // when OnPreUpdate() is not called Render(m_renderTargetHandle, m_config, GetEntityId()); } bool RenderToTextureComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig) { if (auto config = azrtti_cast(baseConfig)) { m_config = *config; return true; } return false; } bool RenderToTextureComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const { if (auto outConfig = azrtti_cast(outBaseConfig)) { *outConfig = m_config; return true; } return false; } int RenderToTextureComponent::GetTextureResourceId() const { return m_renderTargetHandle; } void RenderToTextureComponent::SetEnabled(bool enabled) { if (enabled != m_config.m_enabled) { m_config.m_enabled = enabled; if (gEnv->pGame && gEnv->pGame->GetIGameFramework()) { if (enabled) { gEnv->pGame->GetIGameFramework()->RegisterListener(this, "RenderToTextureComponent", FRAMEWORKLISTENERPRIORITY_HUD); } else { gEnv->pGame->GetIGameFramework()->UnregisterListener(this); } } } } void RenderToTextureComponent::SetWriteSRGBEnabled(bool enabled) { m_config.m_renderContextConfig.m_sRGBWrite = enabled; m_configDirty = true; } void RenderToTextureComponent::SetAlphaMode(AzRTT::AlphaMode mode) { m_config.m_renderContextConfig.m_alphaMode = mode; m_configDirty = true; } void RenderToTextureComponent::OnPostUpdate(float fDeltaTime) { if (m_config.m_displayDebugImage && gEnv->IsEditor() && !gEnv->pConsole->IsOpened()) { DisplayDebugImage(m_config); } } void RenderToTextureComponent::SetCamera(const AZ::EntityId& id) { m_config.m_camera = id; m_configDirty = true; } void RenderToTextureComponent::SetMaxFPS(double fps) { m_config.m_maxFPS = fps; m_configDirty = true; } void RenderToTextureComponent::OnPreUpdate() { // push the changes from the component's RenderContextConfig to our RenderContext // do this here before we render so we avoid threading issues. if (m_configDirty && !m_config.m_renderContextId.IsNull()) { AzRTT::RTTRequestBus::Broadcast(&AzRTT::RTTRequestBus::Events::SetContextConfig, m_config.m_renderContextId, m_config.m_renderContextConfig); m_configDirty = false; } Render(m_renderTargetHandle, m_config, GetEntityId()); } } #endif // if AZ_RENDER_TO_TEXTURE_GEM_ENABLED