implement TSkybox and use setColor method to set the background color, rather than the image

This commit is contained in:
Nick Fisher
2025-06-18 13:01:25 +08:00
parent df393b075b
commit 42f9538040
11 changed files with 177 additions and 30 deletions

View File

@@ -636,7 +636,6 @@ external bool Texture_loadImage(
int level, int level,
); );
@ffi.Native< @ffi.Native<
ffi.Bool Function( ffi.Bool Function(
ffi.Pointer<TEngine>, ffi.Pointer<TEngine>,
@@ -651,7 +650,6 @@ external bool Texture_loadImage(
ffi.Uint32, ffi.Uint32,
ffi.Uint32, ffi.Uint32,
ffi.Uint32, ffi.Uint32,
ffi.Uint32,
ffi.Uint32)>(isLeaf: true) ffi.Uint32)>(isLeaf: true)
external bool Texture_setImage( external bool Texture_setImage(
ffi.Pointer<TEngine> tEngine, ffi.Pointer<TEngine> tEngine,
@@ -664,7 +662,6 @@ external bool Texture_setImage(
int z_offset, int z_offset,
int width, int width,
int height, int height,
int channels,
int depth, int depth,
int bufferFormat, int bufferFormat,
int pixelDataType, int pixelDataType,
@@ -1618,6 +1615,11 @@ external int EntityManager_createEntity(
ffi.Pointer<TEntityManager> tEntityManager, ffi.Pointer<TEntityManager> tEntityManager,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<TFence>)>(isLeaf: true)
external void Fence_waitAndDestroy(
ffi.Pointer<TFence> tFence,
);
@ffi.Native<ffi.Void Function()>(isLeaf: true) @ffi.Native<ffi.Void Function()>(isLeaf: true)
external void RenderThread_create(); external void RenderThread_create();
@@ -1941,6 +1943,14 @@ external void Engine_createFenceRenderThread(
onComplete, onComplete,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<TFence>, ffi.Uint32, VoidCallback)>(
isLeaf: true)
external void Fence_waitAndDestroyRenderThread(
ffi.Pointer<TFence> tFence,
int requestId,
VoidCallback onComplete,
);
@ffi.Native< @ffi.Native<
ffi.Void Function(ffi.Pointer<TEngine>, ffi.Pointer<TFence>, ffi.Uint32, ffi.Void Function(ffi.Pointer<TEngine>, ffi.Pointer<TFence>, ffi.Uint32,
VoidCallback)>(isLeaf: true) VoidCallback)>(isLeaf: true)
@@ -2507,7 +2517,6 @@ external void Texture_loadImageRenderThread(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> onComplete, ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> onComplete,
); );
@ffi.Native< @ffi.Native<
ffi.Void Function( ffi.Void Function(
ffi.Pointer<TEngine>, ffi.Pointer<TEngine>,
@@ -2945,6 +2954,17 @@ external bool GltfResourceLoader_loadResources(
ffi.Pointer<TFilamentAsset> tFilamentAsset, ffi.Pointer<TFilamentAsset> tFilamentAsset,
); );
@ffi.Native<
ffi.Void Function(ffi.Pointer<TSkybox>, ffi.Double, ffi.Double, ffi.Double,
ffi.Double)>(isLeaf: true)
external void Skybox_setColor(
ffi.Pointer<TSkybox> tSkybox,
double r,
double g,
double b,
double a,
);
@ffi.Native< @ffi.Native<
ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId, ffi.Int, ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId, ffi.Int,
ffi.Pointer<TMaterialInstance>)>(isLeaf: true) ffi.Pointer<TMaterialInstance>)>(isLeaf: true)

View File

@@ -1956,6 +1956,13 @@ extension type NativeLibrary(JSObject _) implements JSObject {
Pointer<TGltfResourceLoader> tGltfResourceLoader, Pointer<TGltfResourceLoader> tGltfResourceLoader,
Pointer<TFilamentAsset> tFilamentAsset, Pointer<TFilamentAsset> tFilamentAsset,
); );
external void _Skybox_setColor(
Pointer<TSkybox> tSkybox,
double r,
double g,
double b,
double a,
);
external int _RenderableManager_setMaterialInstanceAt( external int _RenderableManager_setMaterialInstanceAt(
Pointer<TRenderableManager> tRenderableManager, Pointer<TRenderableManager> tRenderableManager,
EntityId entityId, EntityId entityId,
@@ -5509,6 +5516,17 @@ bool GltfResourceLoader_loadResources(
return result == 1; return result == 1;
} }
void Skybox_setColor(
self.Pointer<TSkybox> tSkybox,
double r,
double g,
double b,
double a,
) {
final result = _lib._Skybox_setColor(tSkybox.cast(), r, g, b, a);
return result;
}
bool RenderableManager_setMaterialInstanceAt( bool RenderableManager_setMaterialInstanceAt(
self.Pointer<TRenderableManager> tRenderableManager, self.Pointer<TRenderableManager> tRenderableManager,
DartEntityId entityId, DartEntityId entityId,

View File

@@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:thermion_dart/src/filament/src/implementation/ffi_camera.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_camera.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_skybox.dart';
import 'package:thermion_dart/src/filament/src/interface/scene.dart'; import 'package:thermion_dart/src/filament/src/interface/scene.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_gizmo.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_gizmo.dart';
@@ -10,6 +11,7 @@ import 'package:thermion_dart/src/filament/src/implementation/ffi_scene.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_swapchain.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_swapchain.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_view.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_view.dart';
import 'package:thermion_dart/src/filament/src/interface/skybox.dart';
import 'package:thermion_dart/src/utils/src/matrix.dart'; import 'package:thermion_dart/src/utils/src/matrix.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
@@ -1207,5 +1209,17 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
Vector3(bb.halfExtentX, bb.halfExtentY, bb.halfExtentZ)); Vector3(bb.halfExtentX, bb.halfExtentY, bb.halfExtentZ));
} }
/// Builds an (empty) [Skybox] instance. This will not be attached to any scene until
/// [setSkybox] is called.
///
Future<Skybox> buildSkybox({Texture? texture = null}) async {
final ptr = await withPointerCallback<TSkybox>((cb) {
Engine_buildSkyboxRenderThread(
engine,
(texture as FFITexture?)?.pointer ?? nullptr,
cb,
);
});
return FFISkybox(ptr);
}
} }

View File

@@ -1,6 +1,8 @@
import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_asset.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_indirect_light.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_indirect_light.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_skybox.dart';
import 'package:thermion_dart/src/filament/src/interface/scene.dart'; import 'package:thermion_dart/src/filament/src/interface/scene.dart';
import 'package:thermion_dart/src/filament/src/interface/skybox.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
@@ -153,4 +155,11 @@ class FFIScene extends Scene {
Future<IndirectLight?> getIndirectLight() async { Future<IndirectLight?> getIndirectLight() async {
return _indirectLight; return _indirectLight;
} }
///
///
///
Future setSkybox(Skybox skybox) async {
Scene_setSkybox(scene, (skybox as FFISkybox).pointer);
}
} }

View File

@@ -0,0 +1,26 @@
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
import 'package:thermion_dart/src/filament/src/interface/skybox.dart';
import 'package:thermion_dart/thermion_dart.dart';
class FFISkybox extends Skybox {
final Pointer<TSkybox> pointer;
FFISkybox(this.pointer);
@override
Future setColor(double r, double g, double b, double a) async {
Skybox_setColor(pointer, r, g, b, a);
}
@override
Future destroy() async {
await withVoidCallback(
(requestId, cb) => Engine_destroySkyboxRenderThread(
(FilamentApp.instance as FFIFilamentApp).engine,
pointer,
requestId,
cb,
),
);
}
}

View File

@@ -1,4 +1,5 @@
import 'package:thermion_dart/src/filament/src/interface/scene.dart'; import 'package:thermion_dart/src/filament/src/interface/scene.dart';
import 'package:thermion_dart/src/filament/src/interface/skybox.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
class FilamentConfig<T, U> { class FilamentConfig<T, U> {
@@ -359,4 +360,8 @@ abstract class FilamentApp<T> {
/// ///
Future<Aabb3> getBoundingBox(ThermionEntity entity); Future<Aabb3> getBoundingBox(ThermionEntity entity);
/// Builds a [Skybox] instance. This will not be attached to any scene until
/// [setSkybox] is called.
///
Future<Skybox> buildSkybox({Texture? texture = null});
} }

View File

@@ -1,3 +1,4 @@
import 'package:thermion_dart/src/filament/src/interface/skybox.dart';
import 'package:thermion_dart/thermion_dart.dart'; import 'package:thermion_dart/thermion_dart.dart';
abstract class Scene { abstract class Scene {
@@ -49,4 +50,11 @@ abstract class Scene {
Future<IndirectLight?> getIndirectLight() { Future<IndirectLight?> getIndirectLight() {
throw UnimplementedError(); throw UnimplementedError();
} }
///
///
///
Future setSkybox(Skybox skybox) {
throw UnimplementedError();
}
} }

View File

@@ -0,0 +1,11 @@
abstract class Skybox {
///
///
///
Future setColor(double r, double g, double b, double a);
///
///
///
Future destroy();
}

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'package:thermion_dart/src/filament/src/implementation/background_image.dart'; import 'package:thermion_dart/src/filament/src/implementation/background_image.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_indirect_light.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_indirect_light.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_ktx1_bundle.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_ktx1_bundle.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_skybox.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_swapchain.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_swapchain.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart';
import '../../../../filament/src/implementation/ffi_asset.dart'; import '../../../../filament/src/implementation/ffi_asset.dart';
@@ -229,13 +230,10 @@ class ThermionViewerFFI extends ThermionViewer {
/// ///
@override @override
Future setBackgroundColor(double r, double g, double b, double a) async { Future setBackgroundColor(double r, double g, double b, double a) async {
// we don't want to use the Renderer clearColor, because this only applies await removeSkybox();
// to clearing the swapchain. Even if this Viewer is rendered into the _skybox = await FilamentApp.instance!.buildSkybox() as FFISkybox;
// swapchain, we don't necessarily (?) want to set the clear color, await scene.setSkybox(_skybox!);
// because that will affect other views. await _skybox!.setColor(r, g, b, a);
// We therefore use the background image as the color;
_backgroundImage ??= await BackgroundImage.create(this, scene);
await _backgroundImage!.setBackgroundColor(r, g, b, a);
} }
/// ///
@@ -252,7 +250,7 @@ class ThermionViewerFFI extends ThermionViewer {
Future? _skyboxTextureUploadComplete; Future? _skyboxTextureUploadComplete;
FFITexture? _skyboxTexture; FFITexture? _skyboxTexture;
Pointer<TSkybox>? _skybox; FFISkybox? _skybox;
/// ///
/// ///
@@ -271,10 +269,11 @@ class ThermionViewerFFI extends ThermionViewer {
_skyboxTexture = await bundle.createTexture() as FFITexture; _skyboxTexture = await bundle.createTexture() as FFITexture;
_skybox = await withPointerCallback<TSkybox>((cb) { _skybox = await FilamentApp.instance!.buildSkybox(texture: _skyboxTexture)
Engine_buildSkyboxRenderThread(app.engine, _skyboxTexture!.pointer, cb); as FFISkybox;
});
Scene_setSkybox(scene.scene, _skybox!); await scene.setSkybox(_skybox!);
completer.complete(); completer.complete();
}).then((_) async { }).then((_) async {
_skyboxTextureUploadComplete = null; _skyboxTextureUploadComplete = null;
@@ -364,16 +363,7 @@ class ThermionViewerFFI extends ThermionViewer {
_skyboxTextureUploadComplete = null; _skyboxTextureUploadComplete = null;
} }
if (_skybox != null) { await _skybox?.destroy();
await withVoidCallback(
(requestId, cb) => Engine_destroySkyboxRenderThread(
app.engine,
_skybox!,
requestId,
cb,
),
);
}
_skybox = null; _skybox = null;
_skyboxTexture = null; _skyboxTexture = null;
} }

View File

@@ -0,0 +1,16 @@
#pragma once
#include "APIExport.h"
#include "APIBoundaryTypes.h"
#ifdef __cplusplus
extern "C"
{
#endif
EMSCRIPTEN_KEEPALIVE void Skybox_setColor(TSkybox* tSkybox, double r, double g, double b, double a);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,30 @@
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include "c_api/TSkybox.h"
#include <filament/math/mat4.h>
#include <filament/Skybox.h>
#include "Log.hpp"
#ifdef __cplusplus
namespace thermion
{
extern "C"
{
using namespace filament;
#endif
EMSCRIPTEN_KEEPALIVE void Skybox_setColor(TSkybox *tSkybox, double r, double g, double b, double a)
{
auto *skybox = reinterpret_cast<filament::Skybox *>(tSkybox);
skybox->setColor(filament::math::float4 { static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a) } );
}
#ifdef __cplusplus
}
}
#endif