| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIB_ESCHER_RENDERER_SHADOW_MAP_RENDERER_H_ |
| #define LIB_ESCHER_RENDERER_SHADOW_MAP_RENDERER_H_ |
| |
| #include "lib/escher/escher.h" |
| #include "lib/escher/forward_declarations.h" |
| #include "lib/escher/renderer/renderer.h" |
| #include "lib/escher/renderer/shadow_map.h" |
| #include "lib/escher/scene/camera.h" |
| |
| namespace escher { |
| |
| class ShadowMapRenderer; |
| typedef fxl::RefPtr<ShadowMapRenderer> ShadowMapRendererPtr; |
| |
| // ShadowMapRenderer is used to render the shadow map corresponding to a |
| // stage/model, for a specified light type/position/direction/etc. |
| class ShadowMapRenderer : public Renderer { |
| public: |
| static ShadowMapRendererPtr New(EscherWeakPtr escher, |
| const impl::ModelDataPtr& model_data, |
| const impl::ModelRendererPtr& model_renderer); |
| |
| // Generate a "directional shadow map": one that uses an orthographic |
| // projection. This is used to model very distance light sources (such as the |
| // sun), where the light intensity and direction to the light don't change |
| // appreciably as an object is moved around the stage. |
| virtual ShadowMapPtr GenerateDirectionalShadowMap( |
| const FramePtr& frame, const Stage& stage, const Model& model, |
| const glm::vec3& direction, const glm::vec3& light_color); |
| |
| protected: |
| ShadowMapRenderer(EscherWeakPtr escher, vk::Format shadow_map_format, |
| vk::Format depth_format, |
| const impl::ModelDataPtr& model_data, |
| const impl::ModelRendererPtr& model_renderer, |
| const impl::ModelRenderPassPtr& model_render_pass); |
| ~ShadowMapRenderer() override; |
| |
| void ComputeShadowStageFromSceneStage(const Stage& scene_stage, |
| Stage& shadow_stage); |
| |
| ImagePtr GetTransitionedColorImage(impl::CommandBuffer* command_buffer, |
| uint32_t width, uint32_t height); |
| ImagePtr GetTransitionedDepthImage(impl::CommandBuffer* command_buffer, |
| uint32_t width, uint32_t height); |
| void DrawShadowPass(impl::CommandBuffer* command_buffer, |
| const Stage& shadow_stage, const Model& model, |
| const Camera& camera, ImagePtr& color_image, |
| ImagePtr& depth_image); |
| |
| template <typename ShadowMapT> |
| fxl::RefPtr<ShadowMapT> SubmitPartialFrameAndBuildShadowMap( |
| const FramePtr& frame, const Camera& camera, ImagePtr& color_image, |
| const glm::vec3& light_color) { |
| auto semaphore = escher::Semaphore::New(escher()->vk_device()); |
| frame->SubmitPartialFrame(semaphore); |
| color_image->SetWaitSemaphore(std::move(semaphore)); |
| |
| // NOTE: the bias matrix used for shadowmapping in Vulkan is different than |
| // OpenGL, so we can't use glm::scaleBias(). |
| const mat4 bias(0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, |
| 0.5, 0.5, 0.0, 1.0); |
| return fxl::AdoptRef(new ShadowMapT( |
| std::move(color_image), bias * camera.projection() * camera.transform(), |
| light_color)); |
| } |
| |
| private: |
| vk::Format shadow_map_format_; |
| vk::Format depth_format_; |
| impl::ModelDataPtr model_data_; |
| impl::ModelRendererPtr model_renderer_; |
| impl::ModelRenderPassPtr shadow_map_pass_; |
| std::vector<vk::ClearValue> clear_values_; |
| |
| FRIEND_MAKE_REF_COUNTED(ShadowMapRenderer); |
| FRIEND_REF_COUNTED_THREAD_SAFE(ShadowMapRenderer); |
| FXL_DISALLOW_COPY_AND_ASSIGN(ShadowMapRenderer); |
| }; |
| |
| } // namespace escher |
| |
| #endif // LIB_ESCHER_RENDERER_SHADOW_MAP_RENDERER_H_ |