Flutter Engine
The Flutter Engine
⚠️ 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

std::shared_ptr<impeller::Context> 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.GetRoot().AddChild(
impeller::scene::DirectionalLight(
/* intensity */ 5,
/* direction */ {2, 3, 4}));
Node sphere_node;
Mesh sphere_mesh;
sphere_node.SetGlobalTransform(
Matrix::MakeRotationEuler({kPiOver4, kPiOver4, 0}));
auto sphere_geometry =
impeller::scene::Geometry::MakeSphere(allocator, /* radius */ 2);
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::BlendFactor::kOne, // source_color_factor
impeller::BlendFactor::kOneMinusSourceAlpha, // destination_color_factor
impeller::BlendFactor::kOne, // source_alpha_factor
impeller::BlendFactor::kOneMinusSourceAlpha, // destination_alpha_factor
});
material->SetStencilConfig({
});
sphere_mesh.AddPrimitive({sphere_geometry, material});
sphere_node.SetMesh(sphere_mesh);
Node cube_node;
cube_node.SetLocalTransform(Matrix::MakeTranslation({4, 0, 0}));
Mesh cube_mesh;
allocator, {4, 4, 4});
cube_mesh.AddPrimitive({cube_geometry, material});
cube_node.SetMesh(cube_mesh);
sphere_node.AddChild(cube_node);
scene.GetRoot().AddChild(sphere_node);
/// 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<impeller::Surface> 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;
});
}
static std::shared_ptr< CuboidGeometry > MakeCuboid(Vector3 size)
Definition: geometry.cc:31
VkSurfaceKHR surface
Definition: main.cc:49
Definition: dart.idl:29
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
constexpr float kPiOver4
Definition: math.h:33
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
@ kAlways
Comparison test passes always passes.
@ kIncrementClamp
Increment the current stencil value by 1. Clamp it to the maximum.
static constexpr Color Red()
Definition: color.h:274
static constexpr Color AntiqueWhite()
Definition: color.h:288