blob: 7971535ed838f308a2d1848457ad44d90ac484ac [file] [log] [blame]
// Copyright 2018 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.
#include "lib/escher/renderer/moment_shadow_map_renderer.h"
#include "lib/escher/impl/image_cache.h"
#include "lib/escher/impl/model_moment_shadow_map_pass.h"
#include "lib/escher/impl/vulkan_utils.h"
#include "lib/escher/renderer/moment_shadow_map.h"
#include "lib/escher/scene/stage.h"
namespace {
// Create an image of the same size and format as the input.
escher::ImagePtr CreateSimilarImage(escher::Escher* escher,
escher::impl::CommandBuffer* command_buffer,
const escher::ImagePtr& input) {
escher::ImageInfo info;
info.format = input->format();
info.width = input->width();
info.height = input->height();
info.sample_count = 1;
info.usage =
vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eStorage;
auto output = escher->image_cache()->NewImage(info);
command_buffer->TransitionImageLayout(output, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
return output;
}
} // namespace
namespace escher {
MomentShadowMapRendererPtr MomentShadowMapRenderer::New(
EscherWeakPtr escher, const impl::ModelDataPtr& model_data,
const impl::ModelRendererPtr& model_renderer) {
auto* resource_recycler = escher->resource_recycler();
constexpr vk::Format kShadowMapFormat = vk::Format::eR16G16B16A16Sfloat;
vk::Format depth_format = ESCHER_CHECKED_VK_RESULT(
impl::GetSupportedDepthStencilFormat(escher->vk_physical_device()));
return fxl::MakeRefCounted<MomentShadowMapRenderer>(
std::move(escher), kShadowMapFormat, depth_format, model_data,
model_renderer,
fxl::MakeRefCounted<impl::ModelMomentShadowMapPass>(
resource_recycler, model_data, kShadowMapFormat, depth_format,
/* sample_count= */ 1));
}
MomentShadowMapRenderer::MomentShadowMapRenderer(
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(escher, shadow_map_format, depth_format, model_data,
model_renderer, model_render_pass),
gaussian3x3f16_(std::move(escher)) {}
ShadowMapPtr MomentShadowMapRenderer::GenerateDirectionalShadowMap(
const FramePtr& frame, const Stage& stage, const Model& model,
const glm::vec3& direction, const glm::vec3& light_color) {
auto command_buffer = frame->command_buffer();
auto camera =
Camera::NewForDirectionalShadowMap(stage.viewing_volume(), direction);
Stage shadow_stage;
ComputeShadowStageFromSceneStage(stage, shadow_stage);
auto width = static_cast<uint32_t>(shadow_stage.width());
auto height = static_cast<uint32_t>(shadow_stage.height());
auto color_image = GetTransitionedColorImage(command_buffer, width, height);
auto depth_image = GetTransitionedDepthImage(command_buffer, width, height);
DrawShadowPass(command_buffer, shadow_stage, model, camera, color_image,
depth_image);
frame->AddTimestamp("generated moment shadow map");
command_buffer->TransitionImageLayout(
color_image, vk::ImageLayout::eColorAttachmentOptimal,
vk::ImageLayout::eGeneral);
frame->AddTimestamp("transitioned layout to eGeneral");
auto input_texture = fxl::MakeRefCounted<Texture>(
escher()->resource_recycler(), color_image, vk::Filter::eNearest);
auto blurred_image =
CreateSimilarImage(escher(), command_buffer, color_image);
auto output_texture = fxl::MakeRefCounted<Texture>(
escher()->resource_recycler(), blurred_image, vk::Filter::eNearest);
gaussian3x3f16_.Apply(command_buffer, input_texture, output_texture);
frame->AddTimestamp("applied 3x3 gaussian");
return SubmitPartialFrameAndBuildShadowMap<MomentShadowMap>(
frame, camera, blurred_image, light_color);
}
} // namespace escher