| // 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 |