blob: 5794c95425148c5a712c780052016ed6c052100a [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 "impeller/scene/material.h"
#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/core/sampler_descriptor.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/scene/importer/conversions.h"
#include "impeller/scene/importer/scene_flatbuffers.h"
#include "impeller/scene/pipeline_key.h"
#include "impeller/scene/scene_context.h"
#include "impeller/scene/shaders/unlit.frag.h"
#include <memory>
namespace impeller {
namespace scene {
//------------------------------------------------------------------------------
/// Material
///
Material::~Material() = default;
std::unique_ptr<Material> Material::MakeFromFlatbuffer(
const fb::Material& material,
const std::vector<std::shared_ptr<Texture>>& textures) {
switch (material.type()) {
case fb::MaterialType::kUnlit:
return UnlitMaterial::MakeFromFlatbuffer(material, textures);
case fb::MaterialType::kPhysicallyBased:
return PhysicallyBasedMaterial::MakeFromFlatbuffer(material, textures);
}
}
std::unique_ptr<UnlitMaterial> Material::MakeUnlit() {
return std::make_unique<UnlitMaterial>();
}
std::unique_ptr<PhysicallyBasedMaterial> Material::MakePhysicallyBased() {
return std::make_unique<PhysicallyBasedMaterial>();
}
void Material::SetVertexColorWeight(Scalar weight) {
vertex_color_weight_ = weight;
}
void Material::SetBlendConfig(BlendConfig blend_config) {
blend_config_ = blend_config;
}
void Material::SetStencilConfig(StencilConfig stencil_config) {
stencil_config_ = stencil_config;
}
void Material::SetTranslucent(bool is_translucent) {
is_translucent_ = is_translucent;
}
SceneContextOptions Material::GetContextOptions(const RenderPass& pass) const {
// TODO(bdero): Pipeline blend and stencil config.
return {.sample_count = pass.GetRenderTarget().GetSampleCount()};
}
//------------------------------------------------------------------------------
/// UnlitMaterial
///
std::unique_ptr<UnlitMaterial> UnlitMaterial::MakeFromFlatbuffer(
const fb::Material& material,
const std::vector<std::shared_ptr<Texture>>& textures) {
if (material.type() != fb::MaterialType::kUnlit) {
VALIDATION_LOG << "Cannot unpack unlit material because the ipscene "
"material type is not unlit.";
return nullptr;
}
auto result = Material::MakeUnlit();
if (material.base_color_factor()) {
result->SetColor(importer::ToColor(*material.base_color_factor()));
}
if (material.base_color_texture() >= 0 &&
material.base_color_texture() < static_cast<int32_t>(textures.size())) {
result->SetColorTexture(textures[material.base_color_texture()]);
}
return result;
}
UnlitMaterial::~UnlitMaterial() = default;
void UnlitMaterial::SetColor(Color color) {
color_ = color;
}
void UnlitMaterial::SetColorTexture(std::shared_ptr<Texture> color_texture) {
color_texture_ = std::move(color_texture);
}
// |Material|
MaterialType UnlitMaterial::GetMaterialType() const {
return MaterialType::kUnlit;
}
// |Material|
void UnlitMaterial::BindToCommand(const SceneContext& scene_context,
HostBuffer& buffer,
RenderPass& pass) const {
// Uniform buffer.
UnlitFragmentShader::FragInfo info;
info.color = color_;
info.vertex_color_weight = vertex_color_weight_;
UnlitFragmentShader::BindFragInfo(pass, buffer.EmplaceUniform(info));
// Textures.
SamplerDescriptor sampler_descriptor;
sampler_descriptor.label = "Trilinear";
sampler_descriptor.min_filter = MinMagFilter::kLinear;
sampler_descriptor.mag_filter = MinMagFilter::kLinear;
sampler_descriptor.mip_filter = MipFilter::kLinear;
UnlitFragmentShader::BindBaseColorTexture(
pass,
color_texture_ ? color_texture_ : scene_context.GetPlaceholderTexture(),
scene_context.GetContext()->GetSamplerLibrary()->GetSampler(
sampler_descriptor));
}
//------------------------------------------------------------------------------
/// StandardMaterial
///
std::unique_ptr<PhysicallyBasedMaterial>
PhysicallyBasedMaterial::MakeFromFlatbuffer(
const fb::Material& material,
const std::vector<std::shared_ptr<Texture>>& textures) {
if (material.type() != fb::MaterialType::kPhysicallyBased) {
VALIDATION_LOG << "Cannot unpack unlit material because the ipscene "
"material type is not unlit.";
return nullptr;
}
auto result = Material::MakePhysicallyBased();
result->SetAlbedo(material.base_color_factor()
? importer::ToColor(*material.base_color_factor())
: Color::White());
result->SetRoughness(material.roughness_factor());
result->SetMetallic(material.metallic_factor());
if (material.base_color_texture() >= 0 &&
material.base_color_texture() < static_cast<int32_t>(textures.size())) {
result->SetAlbedoTexture(textures[material.base_color_texture()]);
result->SetVertexColorWeight(0);
}
if (material.metallic_roughness_texture() >= 0 &&
material.metallic_roughness_texture() <
static_cast<int32_t>(textures.size())) {
result->SetMetallicRoughnessTexture(
textures[material.metallic_roughness_texture()]);
}
if (material.normal_texture() >= 0 &&
material.normal_texture() < static_cast<int32_t>(textures.size())) {
result->SetNormalTexture(textures[material.normal_texture()]);
}
if (material.occlusion_texture() >= 0 &&
material.occlusion_texture() < static_cast<int32_t>(textures.size())) {
result->SetOcclusionTexture(textures[material.occlusion_texture()]);
}
return result;
}
PhysicallyBasedMaterial::~PhysicallyBasedMaterial() = default;
void PhysicallyBasedMaterial::SetAlbedo(Color albedo) {
albedo_ = albedo;
}
void PhysicallyBasedMaterial::SetRoughness(Scalar roughness) {
roughness_ = roughness;
}
void PhysicallyBasedMaterial::SetMetallic(Scalar metallic) {
metallic_ = metallic;
}
void PhysicallyBasedMaterial::SetAlbedoTexture(
std::shared_ptr<Texture> albedo_texture) {
albedo_texture_ = std::move(albedo_texture);
}
void PhysicallyBasedMaterial::SetMetallicRoughnessTexture(
std::shared_ptr<Texture> metallic_roughness_texture) {
metallic_roughness_texture_ = std::move(metallic_roughness_texture);
}
void PhysicallyBasedMaterial::SetNormalTexture(
std::shared_ptr<Texture> normal_texture) {
normal_texture_ = std::move(normal_texture);
}
void PhysicallyBasedMaterial::SetOcclusionTexture(
std::shared_ptr<Texture> occlusion_texture) {
occlusion_texture_ = std::move(occlusion_texture);
}
void PhysicallyBasedMaterial::SetEnvironmentMap(
std::shared_ptr<Texture> environment_map) {
environment_map_ = std::move(environment_map);
}
// |Material|
MaterialType PhysicallyBasedMaterial::GetMaterialType() const {
// TODO(bdero): Replace this once a PBR shader has landed.
return MaterialType::kUnlit;
}
// |Material|
void PhysicallyBasedMaterial::BindToCommand(const SceneContext& scene_context,
HostBuffer& buffer,
RenderPass& pass) const {}
} // namespace scene
} // namespace impeller