blob: a7d2266069e82c5649f97cf4e3db006b9e484985 [file] [log] [blame]
// 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_