// 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 namespace impeller { namespace scene { //------------------------------------------------------------------------------ /// Material /// Material::~Material() = default; std::unique_ptr Material::MakeFromFlatbuffer( const fb::Material& material, const std::vector>& 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 Material::MakeUnlit() { return std::make_unique(); } std::unique_ptr Material::MakePhysicallyBased() { return std::make_unique(); } 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::MakeFromFlatbuffer( const fb::Material& material, const std::vector>& 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(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 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::MakeFromFlatbuffer( const fb::Material& material, const std::vector>& 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(textures.size())) { result->SetAlbedoTexture(textures[material.base_color_texture()]); result->SetVertexColorWeight(0); } if (material.metallic_roughness_texture() >= 0 && material.metallic_roughness_texture() < static_cast(textures.size())) { result->SetMetallicRoughnessTexture( textures[material.metallic_roughness_texture()]); } if (material.normal_texture() >= 0 && material.normal_texture() < static_cast(textures.size())) { result->SetNormalTexture(textures[material.normal_texture()]); } if (material.occlusion_texture() >= 0 && material.occlusion_texture() < static_cast(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 albedo_texture) { albedo_texture_ = std::move(albedo_texture); } void PhysicallyBasedMaterial::SetMetallicRoughnessTexture( std::shared_ptr metallic_roughness_texture) { metallic_roughness_texture_ = std::move(metallic_roughness_texture); } void PhysicallyBasedMaterial::SetNormalTexture( std::shared_ptr normal_texture) { normal_texture_ = std::move(normal_texture); } void PhysicallyBasedMaterial::SetOcclusionTexture( std::shared_ptr occlusion_texture) { occlusion_texture_ = std::move(occlusion_texture); } void PhysicallyBasedMaterial::SetEnvironmentMap( std::shared_ptr 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