diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 83d3b324cae10..9883e26b0455a 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1576,6 +1576,21 @@ FILE: ../../../flutter/impeller/runtime_stage/runtime_stage_playground.h FILE: ../../../flutter/impeller/runtime_stage/runtime_stage_unittests.cc FILE: ../../../flutter/impeller/runtime_stage/runtime_types.cc FILE: ../../../flutter/impeller/runtime_stage/runtime_types.h +FILE: ../../../flutter/impeller/scene/camera.cc +FILE: ../../../flutter/impeller/scene/camera.h +FILE: ../../../flutter/impeller/scene/geometry.cc +FILE: ../../../flutter/impeller/scene/geometry.h +FILE: ../../../flutter/impeller/scene/material.cc +FILE: ../../../flutter/impeller/scene/material.h +FILE: ../../../flutter/impeller/scene/scene.cc +FILE: ../../../flutter/impeller/scene/scene.h +FILE: ../../../flutter/impeller/scene/scene_encoder.cc +FILE: ../../../flutter/impeller/scene/scene_encoder.h +FILE: ../../../flutter/impeller/scene/scene_entity.cc +FILE: ../../../flutter/impeller/scene/scene_entity.h +FILE: ../../../flutter/impeller/scene/scene_unittests.cc +FILE: ../../../flutter/impeller/scene/static_mesh_entity.cc +FILE: ../../../flutter/impeller/scene/static_mesh_entity.h FILE: ../../../flutter/impeller/tessellator/c/tessellator.cc FILE: ../../../flutter/impeller/tessellator/c/tessellator.h FILE: ../../../flutter/impeller/tessellator/dart/lib/tessellator.dart diff --git a/impeller/BUILD.gn b/impeller/BUILD.gn index 2fbc00d125343..2920b94f91949 100644 --- a/impeller/BUILD.gn +++ b/impeller/BUILD.gn @@ -86,6 +86,7 @@ impeller_component("impeller_unittests") { "image:image_unittests", "playground", "renderer:renderer_unittests", + "scene:scene_unittests", "typographer:typographer_unittests", ] } diff --git a/impeller/scene/BUILD.gn b/impeller/scene/BUILD.gn new file mode 100644 index 0000000000000..3389ad42bde7b --- /dev/null +++ b/impeller/scene/BUILD.gn @@ -0,0 +1,43 @@ +# 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. + +import("//flutter/impeller/tools/impeller.gni") + +impeller_component("scene") { + sources = [ + "camera.cc", + "camera.h", + "geometry.cc", + "geometry.h", + "material.cc", + "material.h", + "scene.cc", + "scene.h", + "scene_encoder.cc", + "scene_encoder.h", + "scene_entity.cc", + "scene_entity.h", + "static_mesh_entity.cc", + "static_mesh_entity.h", + ] + + public_deps = [ "../renderer" ] + + deps = [ "//flutter/fml" ] +} + +impeller_component("scene_unittests") { + testonly = true + + sources = [ "scene_unittests.cc" ] + + deps = [ + ":scene", + "../fixtures", + "../playground:playground_test", + "//flutter/testing:testing_lib", + + #"//third_party/tinygltf", + ] +} diff --git a/impeller/scene/README.md b/impeller/scene/README.md new file mode 100644 index 0000000000000..c17299293cacd --- /dev/null +++ b/impeller/scene/README.md @@ -0,0 +1,140 @@ +## ⚠️ **Experimental:** Do not use in production! ⚠️ + +# Impeller Scene + +Impeller Scene is an experimental realtime 3D renderer powered by Impeller's +render layer with the following design priorities: + +* Ease of use. +* Suitability for mobile. +* Common case scalability. + +The aim is to create a familiar and flexible scene graph capable of building +complex dynamic scenes for games and beyond. + +## Example + +```cpp +std::shared_ptr context = + /* Create the backend-specific Impeller context */; + +auto allocator = context->GetResourceAllocator(); + +/// Load resources. + +auto dash_gltf = impeller::scene::LoadGLTF(allocator, "models/dash.glb"); +auto environment_hdri = + impeller::scene::LoadHDRI(allocator, "environment/table_mountain.hdr"); + +/// Construct a scene. + +auto scene = impeller::scene::Scene(context); + +scene.Add(dash_gltf.scene); + +auto& dash_player = dash_gltf.scene.CreateAnimationPlayer(); +auto& walk_action = dash_player.CreateClipAction(dash_gltf.GetClip("Walk")); +walk_action.SetLoop(impeller::scene::AnimationAction::kLoopForever); +walk_action.SetWeight(0.7f); +walk_action.Seek(0.0f); +walk_action.Play(); +auto& run_action = dash_player.CreateClipAction(dash_gltf.GetClip("Run")); +run_action.SetLoop(impeller::scene::AnimationAction::kLoopForever); +run_action.SetWeight(0.3f); +run_action.Play(); + +scene.Add( + impeller::scene::DirectionalLight( + /* color */ impeller::Color::AntiqueWhite(), + /* intensity */ 5, + /* direction */ {2, 3, 4})); + +impeller::scene::StaticMeshEntity sphere_entity; +sphere_entity.SetGlobalTransform( + Matrix::MakeRotationEuler({kPiOver4, kPiOver4, 0})); +sphere_entity.SetCullingMode(impeller::scene::CullingMode::kFrustum); + +std::unique_ptr sphere = + impeller::scene::Geometry::MakeSphere(allocator, /* radius */ 2); + +sphere_entity.SetGeometry(sphere); + +auto material = impeller::scene::Material::MakeStandard(); +material.SetAlbedo(impeller::Color::Red()); +material.SetRoughness(0.4); +material.SetMetallic(0.2); +// Common properties shared by all materials. +material.SetEnvironmentMap(environment_hdri); +material.SetFlatShaded(true); +material.SetBlendConfig({ + impeller::BlendOperation::kAdd, // color_op + impeller::BlendFactor::kOne, // source_color_factor + impeller::BlendFactor::kOneMinusSourceAlpha, // destination_color_factor + impeller::BlendOperation::kAdd, // alpha_op + impeller::BlendFactor::kOne, // source_alpha_factor + impeller::BlendFactor::kOneMinusSourceAlpha, // destination_alpha_factor +}); +material.SetStencilConfig({ + impeller::StencilOperation::kIncrementClamp, // operation + impeller::CompareFunction::kAlways, // compare +}); + +sphere_entity->SetMaterials({material}); + + +impeller::scene::StaticMeshEntity cube_entity; +cube_entity.GetGeometry( + impeller::scene::Geometry::MakeCube(allocator, {4, 4, 4})); +cube_entity.SetMaterials({material}); + +cube_entity.SetLocalTransform(Matrix::MakeTranslation({4, 0, 0})); + +sphere_entity->Add(sube_entity); +scene.Add(sphere_entity); + +/// Post processing. + +auto dof = impeller::scene::PostProcessingEffect::MakeBokeh( + /* aperture_size */ 0.2, + /* focus_plane_distance */ 50); +scene.SetPostProcessing({dof}); + +/// Render the scene. + +auto renderer = impeller::Renderer(context); + +while(true) { + std::unique_ptr surface = /* Wrap the window surface */; + + renderer->Render(surface, [&scene](RenderTarget& render_target) { + /// Render a perspective view. + + auto camera = + impeller::Camera::MakePerspective( + /* fov */ kPiOver4, + /* position */ {50, -30, 50}) + .LookAt( + /* target */ impeller::Vector3::Zero, + /* up */ {0, -1, 0}); + + scene.Render(render_target, camera); + + /// Render an overhead view on the bottom right corner of the screen. + + auto size = render_target.GetRenderTargetSize(); + auto minimap_camera = + impeller::Camera::MakeOrthographic( + /* view */ Rect::MakeLTRB(-100, -100, 100, 100), + /* position */ {0, -50, 0}) + .LookAt( + /* target */ impeller::Vector3::Zero, + /* up */ {0, 0, 1}) + .WithViewport(IRect::MakeXYWH(size.width / 4, size.height / 4, + size.height / 5, size.height / 5)); + + scene.Render(render_target, minimap_camera); + + return true; + }); +} +``` diff --git a/impeller/scene/camera.cc b/impeller/scene/camera.cc new file mode 100644 index 0000000000000..b10673bd4899c --- /dev/null +++ b/impeller/scene/camera.cc @@ -0,0 +1,37 @@ +// 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/camera.h" + +namespace impeller { +namespace scene { + +Camera Camera::MakePerspective(Scalar fov_y, Vector3 position) { + Camera camera; + camera.fov_y_ = fov_y; + camera.position_ = position; + return camera; +} + +Camera Camera::LookAt(Vector3 target, Vector3 up) const { + Camera camera = *this; + camera.target_ = target; + camera.up_ = up; + return camera; +} + +Matrix Camera::GetTransform(ISize target_size) const { + if (transform_.has_value()) { + return transform_.value(); + } + + transform_ = + Matrix::MakePerspective(Radians(fov_y_), target_size, z_near_, z_far_) * + Matrix::MakeLookAt(position_, target_, up_).Invert(); + + return transform_.value(); +} + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/camera.h b/impeller/scene/camera.h new file mode 100644 index 0000000000000..0eb02376ef684 --- /dev/null +++ b/impeller/scene/camera.h @@ -0,0 +1,34 @@ +// 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. + +#pragma once + +#include + +#include "impeller/geometry/matrix.h" + +namespace impeller { +namespace scene { + +class Camera { + public: + static Camera MakePerspective(Scalar fov_y, Vector3 position); + + Camera LookAt(Vector3 target, Vector3 up = Vector3(0, -1, 0)) const; + + Matrix GetTransform(ISize target_size) const; + + private: + Scalar fov_y_ = 60; + Vector3 position_ = Vector3(); + Vector3 target_ = Vector3(0, 0, -1); + Vector3 up_ = Vector3(0, -1, 0); + Scalar z_near_ = 0.1; + Scalar z_far_ = 1000; + + mutable std::optional transform_; +}; + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/geometry.cc b/impeller/scene/geometry.cc new file mode 100644 index 0000000000000..47ed75f18b6d5 --- /dev/null +++ b/impeller/scene/geometry.cc @@ -0,0 +1,36 @@ +// 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/geometry.h" + +#include + +namespace impeller { +namespace scene { + +//------------------------------------------------------------------------------ +/// Geometry +/// + +std::shared_ptr Geometry::MakeCuboid(Vector3 size) { + auto result = std::make_shared(); + result->SetSize(size); + return result; +} + +//------------------------------------------------------------------------------ +/// CuboidGeometry +/// + +void CuboidGeometry::SetSize(Vector3 size) { + size_ = size; +} + +VertexBuffer CuboidGeometry::GetVertexBuffer( + std::shared_ptr& allocator) const { + return {}; +} + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/geometry.h b/impeller/scene/geometry.h new file mode 100644 index 0000000000000..f0e7e47eb38bd --- /dev/null +++ b/impeller/scene/geometry.h @@ -0,0 +1,39 @@ +// 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. + +#pragma once + +#include + +#include "impeller/geometry/vector.h" +#include "impeller/renderer/allocator.h" +#include "impeller/renderer/vertex_buffer.h" + +namespace impeller { +namespace scene { + +class CuboidGeometry; + +class Geometry { + public: + static std::shared_ptr MakeCuboid(Vector3 size); + + private: + virtual VertexBuffer GetVertexBuffer( + std::shared_ptr& allocator) const = 0; +}; + +class CuboidGeometry final : public Geometry { + public: + void SetSize(Vector3 size); + + private: + VertexBuffer GetVertexBuffer( + std::shared_ptr& allocator) const override; + + Vector3 size_; +}; + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/material.cc b/impeller/scene/material.cc new file mode 100644 index 0000000000000..a38a14a4f539f --- /dev/null +++ b/impeller/scene/material.cc @@ -0,0 +1,82 @@ +// 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 + +namespace impeller { +namespace scene { + +//------------------------------------------------------------------------------ +/// Material +/// + +std::unique_ptr Material::MakeUnlit() { + return std::make_unique(); +} + +std::unique_ptr Material::MakeStandard() { + return std::make_unique(); +} + +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; +} + +//------------------------------------------------------------------------------ +/// UnlitMaterial +/// + +void UnlitMaterial::SetColor(Color color) { + color_ = color; +} + +//------------------------------------------------------------------------------ +/// StandardMaterial +/// + +void StandardMaterial::SetAlbedo(Color albedo) { + albedo_ = albedo; +} + +void StandardMaterial::SetRoughness(Scalar roughness) { + roughness_ = roughness; +} + +void StandardMaterial::SetMetallic(Scalar metallic) { + metallic_ = metallic; +} + +void StandardMaterial::SetAlbedoTexture( + std::shared_ptr albedo_texture) { + albedo_texture_ = std::move(albedo_texture); +} + +void StandardMaterial::SetNormalTexture( + std::shared_ptr normal_texture) { + normal_texture_ = std::move(normal_texture); +} + +void StandardMaterial::SetOcclusionRoughnessMetallicTexture( + std::shared_ptr occlusion_roughness_metallic_texture) { + occlusion_roughness_metallic_texture_ = + std::move(occlusion_roughness_metallic_texture); +} + +void StandardMaterial::SetEnvironmentMap( + std::shared_ptr environment_map) { + environment_map_ = std::move(environment_map); +} + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/material.h b/impeller/scene/material.h new file mode 100644 index 0000000000000..a9e0be7a3ba7c --- /dev/null +++ b/impeller/scene/material.h @@ -0,0 +1,83 @@ +// 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. + +#pragma once + +#include + +#include "impeller/geometry/scalar.h" +#include "impeller/renderer/formats.h" +#include "impeller/renderer/texture.h" + +namespace impeller { +namespace scene { + +class UnlitMaterial; +class StandardMaterial; + +class Material { + public: + struct BlendConfig { + BlendOperation color_op = BlendOperation::kAdd; + BlendFactor source_color_factor = BlendFactor::kOne; + BlendFactor destination_color_factor = BlendFactor::kOneMinusSourceAlpha; + BlendOperation alpha_op = BlendOperation::kAdd; + BlendFactor source_alpha_factor = BlendFactor::kOne; + BlendFactor destination_alpha_factor = BlendFactor::kOneMinusSourceAlpha; + }; + + struct StencilConfig { + StencilOperation operation = StencilOperation::kKeep; + CompareFunction compare = CompareFunction::kAlways; + }; + + static std::unique_ptr MakeUnlit(); + static std::unique_ptr MakeStandard(); + + void SetBlendConfig(BlendConfig blend_config); + void SetStencilConfig(StencilConfig stencil_config); + + void SetTranslucent(bool is_translucent); + + protected: + BlendConfig blend_config_; + StencilConfig stencil_config_; + bool is_translucent_ = false; +}; + +class UnlitMaterial final : public Material { + public: + void SetColor(Color color); + + private: + Color color_; +}; + +class StandardMaterial final : public Material { + public: + void SetAlbedo(Color albedo); + void SetRoughness(Scalar roughness); + void SetMetallic(Scalar metallic); + + void SetAlbedoTexture(std::shared_ptr albedo_texture); + void SetNormalTexture(std::shared_ptr normal_texture); + void SetOcclusionRoughnessMetallicTexture( + std::shared_ptr occlusion_roughness_metallic_texture); + + void SetEnvironmentMap(std::shared_ptr environment_map); + + private: + Color albedo_ = Color::CornflowerBlue(); + Scalar roughness_ = 0.5; + Scalar metallic_ = 0.5; + + std::shared_ptr albedo_texture_; + std::shared_ptr normal_texture_; + std::shared_ptr occlusion_roughness_metallic_texture_; + + std::shared_ptr environment_map_; +}; + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/scene.cc b/impeller/scene/scene.cc new file mode 100644 index 0000000000000..4a4cba16a59fc --- /dev/null +++ b/impeller/scene/scene.cc @@ -0,0 +1,47 @@ +// 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/scene.h" + +#include +#include + +#include "flutter/fml/logging.h" +#include "impeller/renderer/render_target.h" +#include "impeller/scene/scene_encoder.h" + +namespace impeller { +namespace scene { + +Scene::Scene(const std::shared_ptr& context) : context_(context){}; + +void Scene::Add(const std::shared_ptr& child) { + root_.Add(child); +} + +bool Scene::Render(const RenderTarget& render_target, + const Camera& camera) const { + // Collect the render commands from the scene. + SceneEncoder encoder; + if (!root_.Render(encoder, camera)) { + FML_LOG(ERROR) << "Failed to render frame."; + return false; + } + + // Encode the commands. + std::shared_ptr command_buffer = + encoder.BuildSceneCommandBuffer(*context_, render_target); + + // TODO(bdero): Do post processing. + + if (!command_buffer->SubmitCommands()) { + FML_LOG(ERROR) << "Failed to submit command buffer."; + return false; + } + + return true; +} + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/scene.h b/impeller/scene/scene.h new file mode 100644 index 0000000000000..6a69e79e2be3f --- /dev/null +++ b/impeller/scene/scene.h @@ -0,0 +1,35 @@ +// 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. + +#pragma once + +#include +#include + +#include "flutter/fml/macros.h" + +#include "impeller/renderer/render_target.h" +#include "impeller/scene/camera.h" +#include "impeller/scene/scene_entity.h" + +namespace impeller { +namespace scene { + +class Scene { + public: + Scene() = delete; + explicit Scene(const std::shared_ptr& context); + + void Add(const std::shared_ptr& child); + bool Render(const RenderTarget& render_target, const Camera& camera) const; + + private: + std::shared_ptr context_; + SceneEntity root_; + + FML_DISALLOW_COPY_AND_ASSIGN(Scene); +}; + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/scene_encoder.cc b/impeller/scene/scene_encoder.cc new file mode 100644 index 0000000000000..456a86df644d3 --- /dev/null +++ b/impeller/scene/scene_encoder.cc @@ -0,0 +1,29 @@ +// 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 "flutter/fml/macros.h" + +#include "fml/logging.h" +#include "impeller/renderer/render_target.h" +#include "impeller/scene/scene_encoder.h" + +namespace impeller { +namespace scene { + +SceneEncoder::SceneEncoder() = default; + +std::shared_ptr SceneEncoder::BuildSceneCommandBuffer( + Context& context, + const RenderTarget& render_target) const { + auto command_buffer = context.CreateCommandBuffer(); + if (!command_buffer) { + FML_LOG(ERROR) << "Failed to create command buffer."; + return nullptr; + } + + return command_buffer; +} + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/scene_encoder.h b/impeller/scene/scene_encoder.h new file mode 100644 index 0000000000000..2b8f15cab1cdd --- /dev/null +++ b/impeller/scene/scene_encoder.h @@ -0,0 +1,32 @@ +// 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. + +#pragma once + +#include + +#include "flutter/fml/macros.h" + +#include "impeller/renderer/command_buffer.h" + +namespace impeller { +namespace scene { + +class Scene; + +class SceneEncoder { + private: + SceneEncoder(); + + std::shared_ptr BuildSceneCommandBuffer( + Context& context, + const RenderTarget& render_target) const; + + friend Scene; + + FML_DISALLOW_COPY_AND_ASSIGN(SceneEncoder); +}; + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/scene_entity.cc b/impeller/scene/scene_entity.cc new file mode 100644 index 0000000000000..4183849a9e865 --- /dev/null +++ b/impeller/scene/scene_entity.cc @@ -0,0 +1,74 @@ +// 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/scene_entity.h" + +#include + +#include "impeller/base/validation.h" +#include "impeller/geometry/matrix.h" +#include "impeller/scene/scene_encoder.h" +#include "impeller/scene/static_mesh_entity.h" + +namespace impeller { +namespace scene { + +SceneEntity::SceneEntity() = default; + +SceneEntity::~SceneEntity() = default; + +std::shared_ptr SceneEntity::MakeStaticMesh() { + return std::make_shared(); +} + +void SceneEntity::SetLocalTransform(Matrix transform) { + local_transform_ = transform; +} + +Matrix SceneEntity::GetLocalTransform() const { + return local_transform_; +} + +void SceneEntity::SetGlobalTransform(Matrix transform) { + Matrix inverse_global_transform = + parent_ ? parent_->GetGlobalTransform().Invert() : Matrix(); + + local_transform_ = inverse_global_transform * transform; +} + +Matrix SceneEntity::GetGlobalTransform() const { + if (parent_) { + return parent_->GetGlobalTransform() * local_transform_; + } + return local_transform_; +} + +bool SceneEntity::Add(const std::shared_ptr& child) { + if (child->parent_ != nullptr) { + VALIDATION_LOG << "Cannot add SceneEntity as a child because it already " + "has a parent assigned."; + return false; + } + + children_.push_back(child); + child->parent_ = this; + return true; +} + +bool SceneEntity::Render(SceneEncoder& encoder, const Camera& camera) const { + OnRender(encoder, camera); + for (auto& child : children_) { + if (!child->Render(encoder, camera)) { + return false; + } + } + return true; +} + +bool SceneEntity::OnRender(SceneEncoder& encoder, const Camera& camera) const { + return true; +} + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/scene_entity.h b/impeller/scene/scene_entity.h new file mode 100644 index 0000000000000..694d0cd3616fe --- /dev/null +++ b/impeller/scene/scene_entity.h @@ -0,0 +1,52 @@ +// 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. + +#pragma once + +#include +#include + +#include "flutter/fml/macros.h" + +#include "impeller/geometry/matrix.h" +#include "impeller/renderer/render_target.h" +#include "impeller/scene/camera.h" +#include "impeller/scene/scene_encoder.h" + +namespace impeller { +namespace scene { + +class StaticMeshEntity; + +class SceneEntity { + public: + SceneEntity(); + virtual ~SceneEntity(); + + static std::shared_ptr MakeStaticMesh(); + + void SetLocalTransform(Matrix transform); + Matrix GetLocalTransform() const; + + void SetGlobalTransform(Matrix transform); + Matrix GetGlobalTransform() const; + + bool Add(const std::shared_ptr& child); + + bool Render(SceneEncoder& encoder, const Camera& camera) const; + + protected: + Matrix local_transform_; + + private: + virtual bool OnRender(SceneEncoder& encoder, const Camera& camera) const; + + SceneEntity* parent_ = nullptr; + std::vector> children_; + + FML_DISALLOW_COPY_AND_ASSIGN(SceneEntity); +}; + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/scene_unittests.cc b/impeller/scene/scene_unittests.cc new file mode 100644 index 0000000000000..3388c7062b54f --- /dev/null +++ b/impeller/scene/scene_unittests.cc @@ -0,0 +1,64 @@ +// 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 "flutter/testing/testing.h" +#include "impeller/geometry/color.h" +#include "impeller/geometry/constants.h" +#include "impeller/geometry/matrix.h" +#include "impeller/geometry/vector.h" +#include "impeller/playground/playground.h" +#include "impeller/playground/playground_test.h" + +#include "impeller/scene/camera.h" +#include "impeller/scene/geometry.h" +#include "impeller/scene/material.h" +#include "impeller/scene/scene.h" +#include "impeller/scene/static_mesh_entity.h" + +// #include "third_party/tinygltf/tiny_gltf.h" + +namespace impeller { +namespace scene { +namespace testing { + +using SceneTest = PlaygroundTest; +INSTANTIATE_PLAYGROUND_SUITE(SceneTest); + +TEST_P(SceneTest, UnlitScene) { + auto allocator = GetContext()->GetResourceAllocator(); + auto scene = Scene(GetContext()); + + { + auto mesh = SceneEntity::MakeStaticMesh(); + + auto material = Material::MakeUnlit(); + material->SetColor(Color::Red()); + mesh->SetMaterial(std::move(material)); + + Vector3 size(1, 2, 3); + mesh->SetGeometry(Geometry::MakeCuboid(size)); + + mesh->SetLocalTransform(Matrix::MakeTranslation(size / 2)); + + scene.Add(mesh); + } + + Renderer::RenderCallback callback = [&](RenderTarget& render_target) { + auto camera = Camera::MakePerspective( + /* fov */ kPiOver4, + /* position */ {50, -30, 50}) + .LookAt( + /* target */ Vector3(), + /* up */ {0, -1, 0}); + + scene.Render(render_target, camera); + return true; + }; + + OpenPlaygroundHere(callback); +} + +} // namespace testing +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/static_mesh_entity.cc b/impeller/scene/static_mesh_entity.cc new file mode 100644 index 0000000000000..493d342b87e0e --- /dev/null +++ b/impeller/scene/static_mesh_entity.cc @@ -0,0 +1,30 @@ +// 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/static_mesh_entity.h" +#include +#include "impeller/scene/material.h" + +namespace impeller { +namespace scene { + +StaticMeshEntity::StaticMeshEntity() = default; +StaticMeshEntity::~StaticMeshEntity() = default; + +void StaticMeshEntity::SetGeometry(std::shared_ptr geometry) { + geometry_ = std::move(geometry); +} + +void StaticMeshEntity::SetMaterial(std::shared_ptr material) { + material_ = std::move(material); +} + +// |SceneEntity| +bool StaticMeshEntity::OnRender(SceneEncoder& encoder, + const Camera& camera) const { + return true; +} + +} // namespace scene +} // namespace impeller diff --git a/impeller/scene/static_mesh_entity.h b/impeller/scene/static_mesh_entity.h new file mode 100644 index 0000000000000..7a1df4543d973 --- /dev/null +++ b/impeller/scene/static_mesh_entity.h @@ -0,0 +1,37 @@ +// 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. + +#pragma once + +#include +#include + +#include "flutter/fml/macros.h" +#include "impeller/scene/geometry.h" +#include "impeller/scene/material.h" +#include "impeller/scene/scene_entity.h" + +namespace impeller { +namespace scene { + +class StaticMeshEntity final : public SceneEntity { + public: + StaticMeshEntity(); + ~StaticMeshEntity(); + + void SetGeometry(std::shared_ptr material); + void SetMaterial(std::shared_ptr material); + + private: + // |SceneEntity| + bool OnRender(SceneEncoder& encoder, const Camera& camera) const override; + + std::shared_ptr material_; + std::shared_ptr geometry_; + + FML_DISALLOW_COPY_AND_ASSIGN(StaticMeshEntity); +}; + +} // namespace scene +} // namespace impeller