blob: c9e6f3c1a60a47fb86d9c22ad16afb240d6de59c [file] [log] [blame] [edit]
// Copyright 2013 The Flutter 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 "the_impeller_example.h"
#include <filesystem>
#include <iostream>
#include "impeller/core/host_buffer.h"
#include "impeller/renderer/command.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/render_target.h"
#include "impeller/renderer/sampler_library.h"
#include "impeller/renderer/vertex_buffer_builder.h"
#include "examples/assets.h"
#include "generated/shaders/impeller.frag.h"
#include "generated/shaders/impeller.vert.h"
namespace example {
ExampleBase::Info TheImpellerExample::GetInfo() {
return {
.name = "The Impeller",
.description =
"One draw call with a textured quad. The fragment shader renders a "
"fancy SDF scene with a cubemap backdrop.",
};
}
bool TheImpellerExample::Setup(impeller::Context& context) {
transients_buffer_ =
impeller::HostBuffer::Create(context.GetResourceAllocator());
const auto fixture_path =
std::filesystem::current_path() /
"third_party/impeller-cmake/third_party/flutter/impeller/fixtures/";
const auto blue_noise_path =
(fixture_path / "blue_noise.png").generic_string();
blue_noise_texture_ = example::LoadTexture(blue_noise_path.c_str(),
*context.GetResourceAllocator());
if (!blue_noise_texture_) {
std::cerr << "Failed to load blue noise texture." << std::endl;
return false;
}
cube_map_texture_ =
example::LoadTextureCube({fixture_path / "table_mountain_px.png",
fixture_path / "table_mountain_nx.png",
fixture_path / "table_mountain_py.png",
fixture_path / "table_mountain_ny.png",
fixture_path / "table_mountain_pz.png",
fixture_path / "table_mountain_nz.png"},
*context.GetResourceAllocator());
auto pipeline_desc =
impeller::PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(context);
pipeline_desc->SetSampleCount(impeller::SampleCount::kCount4);
pipeline_ = context.GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
if (!pipeline_ || !pipeline_->IsValid()) {
std::cerr << "Failed to initialize pipeline for showcase.";
return false;
}
return true;
}
bool TheImpellerExample::Render(impeller::Context& context,
const impeller::RenderTarget& render_target,
impeller::CommandBuffer& command_buffer) {
clock_.Tick();
transients_buffer_->Reset();
auto pass = command_buffer.CreateRenderPass(render_target);
if (!pass) {
return false;
}
pass->SetCommandLabel("Impeller SDF showcase");
pass->SetPipeline(pipeline_);
auto size = render_target.GetRenderTargetSize();
impeller::VertexBufferBuilder<VS::PerVertexData> builder;
builder.AddVertices({{impeller::Point()},
{impeller::Point(0, size.height)},
{impeller::Point(size.width, 0)},
{impeller::Point(size.width, 0)},
{impeller::Point(0, size.height)},
{impeller::Point(size.width, size.height)}});
pass->SetVertexBuffer(builder.CreateVertexBuffer(*transients_buffer_));
VS::FrameInfo vs_uniform;
vs_uniform.mvp = impeller::Matrix::MakeOrthographic(size);
VS::BindFrameInfo(*pass, transients_buffer_->EmplaceUniform((vs_uniform)));
FS::FragInfo fs_uniform;
fs_uniform.texture_size = impeller::Point(size);
fs_uniform.time = clock_.GetTime();
FS::BindFragInfo(*pass, transients_buffer_->EmplaceUniform(fs_uniform));
impeller::SamplerDescriptor noise_sampler_desc;
noise_sampler_desc.width_address_mode = impeller::SamplerAddressMode::kRepeat;
noise_sampler_desc.height_address_mode =
impeller::SamplerAddressMode::kRepeat;
FS::BindBlueNoise(
*pass, blue_noise_texture_,
context.GetSamplerLibrary()->GetSampler(noise_sampler_desc));
FS::BindCubeMap(*pass, cube_map_texture_,
context.GetSamplerLibrary()->GetSampler({}));
if (!pass->Draw().ok()) {
return false;
}
if (!pass->EncodeCommands()) {
return false;
}
return true;
}
} // namespace example