diff --git a/thermion_dart/lib/src/filament/src/implementation/ffi_view.dart b/thermion_dart/lib/src/filament/src/implementation/ffi_view.dart index 1798a18a..82a5fe95 100644 --- a/thermion_dart/lib/src/filament/src/implementation/ffi_view.dart +++ b/thermion_dart/lib/src/filament/src/implementation/ffi_view.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:logging/logging.dart'; +import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart'; import 'package:thermion_dart/src/filament/src/interface/scene.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart'; import 'package:thermion_dart/src/filament/src/implementation/ffi_render_target.dart'; @@ -189,7 +190,8 @@ class FFIView extends View { var viewport = await getViewport(); y = viewport.height - y; if (FILAMENT_WASM) { - View_pickRenderThread(view, pickRequestId, x, y, _onPickResultHolder.pointer); + View_pickRenderThread( + view, pickRequestId, x, y, _onPickResultHolder.pointer); } else { View_pick(view, pickRequestId, x, y, _onPickResultHolder.pointer); } @@ -218,4 +220,25 @@ class FFIView extends View { fragZ: fragZ, )); } + + @override + Future setFogOptions(FogOptions options) async { + final tFogOptions = Struct.create(); + tFogOptions.cutOffDistance = options.cutOffDistance; + tFogOptions.enabled = options.enabled; + tFogOptions.density = options.density; + tFogOptions.distance = options.distance; + tFogOptions.fogColorFromIbl = options.fogColorFromIbl; + tFogOptions.height = options.height; + tFogOptions.heightFalloff = options.heightFalloff; + tFogOptions.inScatteringSize = options.inScatteringSize; + tFogOptions.inScatteringStart = options.inScatteringStart; + tFogOptions.maximumOpacity = options.maximumOpacity; + tFogOptions.skyColor = + (options.skyColor as FFITexture?)?.pointer ?? nullptr; + tFogOptions.linearColor.x = options.linearColor.r; + tFogOptions.linearColor.y = options.linearColor.x; + tFogOptions.linearColor.z = options.linearColor.x; + View_setFogOptions(this.view, tFogOptions.address); + } } diff --git a/thermion_dart/lib/src/filament/src/interface/view.dart b/thermion_dart/lib/src/filament/src/interface/view.dart index 49192ec3..9c436e7d 100644 --- a/thermion_dart/lib/src/filament/src/interface/view.dart +++ b/thermion_dart/lib/src/filament/src/interface/view.dart @@ -2,10 +2,39 @@ import 'package:thermion_dart/src/filament/src/interface/layers.dart'; import 'package:thermion_dart/src/filament/src/interface/scene.dart'; import 'package:thermion_dart/thermion_dart.dart'; -enum BlendMode { - opaque, - transparent +class FogOptions { + final double distance; + final double cutOffDistance; + final double maximumOpacity; + final double height; + final double heightFalloff; + late final Vector3 linearColor; + final double density; + final double inScatteringStart; + final double inScatteringSize; + final bool fogColorFromIbl; + final Texture? skyColor; + final bool enabled; + + FogOptions( + {this.enabled = false, + this.distance = 0.0, + this.cutOffDistance = double.infinity, + this.maximumOpacity = 1.0, + this.height = 0, + this.heightFalloff = 1, + Vector3? linearColor = null, + this.density = 0.1, + this.inScatteringStart = 0, + this.inScatteringSize = -1, + this.fogColorFromIbl = false, + this.skyColor = null}) { + this.linearColor = linearColor ?? Vector3(1, 1, 1); + } } + +enum BlendMode { opaque, transparent } + /// /// The viewport currently attached to a [View]. /// @@ -23,6 +52,10 @@ class Viewport { enum QualityLevel { LOW, MEDIUM, HIGH, ULTRA } abstract class View { + + /// Gets the scene currently associated with this View. + /// + /// Future getScene(); Future getViewport(); Future setViewport(int width, int height); @@ -43,24 +76,26 @@ abstract class View { Future setBloom(bool enabled, double strength); Future setBlendMode(BlendMode blendMode); Future setRenderQuality(QualityLevel quality); + Future setLayerVisibility(VisibilityLayers layer, bool visible); - - + + /// Sets the fog options for this view. + /// Fog is disabled by default + /// + Future setFogOptions(FogOptions options); + + /// + /// Call [pick] to hit-test renderable entities at given viewport coordinates + /// (or use one of the provided [InputHandler] classes which does this for you under the hood) /// - /// Call [pick] to hit-test renderable entities at given viewport coordinates - /// (or use one of the provided [InputHandler] classes which does this for you under the hood) - /// /// Picking is an asynchronous operation that will usually take 2-3 frames to complete (so ensure you are calling render). /// /// [x] and [y] must be in local logical coordinates (i.e. where 0,0 is at top-left of the viewport). /// Future pick(int x, int y, void Function(PickResult) resultHandler); - /// /// /// Future dispose(); - - } diff --git a/thermion_dart/native/include/c_api/TView.h b/thermion_dart/native/include/c_api/TView.h index 8d2ff4ec..0913b716 100644 --- a/thermion_dart/native/include/c_api/TView.h +++ b/thermion_dart/native/include/c_api/TView.h @@ -17,6 +17,24 @@ struct TViewport { }; typedef struct TViewport TViewport; +/** + * Copied from FogOptions in View.h + */ +struct TFogOptions { + float distance = 0.0f; + float cutOffDistance = INFINITY; + float maximumOpacity = 1.0f; + float height = 0.0f; + float heightFalloff = 1.0f; + double3 linearColor = { 1.0f, 1.0f, 1.0f }; + float density = 0.1f; + float inScatteringStart = 0.0f; + float inScatteringSize = -1.0f; + bool fogColorFromIbl = false; + TTexture* skyColor = nullptr; + bool enabled = false; +}; + enum TToneMapping { ACES, @@ -68,6 +86,7 @@ EMSCRIPTEN_KEEPALIVE void View_setDitheringEnabled(TView *tView, bool enabled); EMSCRIPTEN_KEEPALIVE bool View_isDitheringEnabled(TView *tView); EMSCRIPTEN_KEEPALIVE void View_setScene(TView *tView, TScene *tScene); EMSCRIPTEN_KEEPALIVE void View_setFrontFaceWindingInverted(TView *tView, bool inverted); +EMSCRIPTEN_KEEPALIVE void View_setFogOptions(TView *tView, TFogOptions *tFogOptions); typedef void (*PickCallback)(uint32_t requestId, EntityId entityId, float depth, float fragX, float fragY, float fragZ); EMSCRIPTEN_KEEPALIVE void View_pick(TView* tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback); diff --git a/thermion_dart/native/src/c_api/TView.cpp b/thermion_dart/native/src/c_api/TView.cpp index bca3c95c..a884601d 100644 --- a/thermion_dart/native/src/c_api/TView.cpp +++ b/thermion_dart/native/src/c_api/TView.cpp @@ -1,6 +1,6 @@ #ifdef __EMSCRIPTEN__ #include -#endif +#endif #include #include @@ -13,205 +13,220 @@ #include "Log.hpp" #ifdef __cplusplus -namespace thermion { -extern "C" +namespace thermion { -using namespace filament; + extern "C" + { + using namespace filament; #endif - EMSCRIPTEN_KEEPALIVE void View_setBlendMode(TView *tView, TBlendMode tBlendMode) { - auto view = reinterpret_cast(tView); - view->setBlendMode(static_cast(tBlendMode)); - } - - EMSCRIPTEN_KEEPALIVE TViewport View_getViewport(TView *tView) - { - auto view = reinterpret_cast(tView); - auto & vp = view->getViewport(); - TViewport tvp; - tvp.left = vp.left; - tvp.bottom = vp.bottom; - tvp.width = vp.width; - tvp.height = vp.height; - return tvp; - } - - EMSCRIPTEN_KEEPALIVE void View_setViewport(TView *tView, uint32_t width, uint32_t height) - { - auto view = reinterpret_cast(tView); - view->setViewport({0, 0, width, height}); - TRACE("Set viewport to %dx%d", width, height); - } - - EMSCRIPTEN_KEEPALIVE TRenderTarget *View_getRenderTarget(TView *tView) { - auto view = reinterpret_cast(tView); - auto tRenderTarget = reinterpret_cast(view->getRenderTarget()); - return tRenderTarget; - } - - EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *tView, TRenderTarget *tRenderTarget) - { - auto view = reinterpret_cast(tView); - auto renderTarget = reinterpret_cast(tRenderTarget); - view->setRenderTarget(renderTarget); - } - - EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *tView, bool enabled) - { - auto view = reinterpret_cast(tView); - view->setFrustumCullingEnabled(enabled); - } - - EMSCRIPTEN_KEEPALIVE void View_setPostProcessing(TView *tView, bool enabled) - { - auto view = reinterpret_cast(tView); - view->setPostProcessingEnabled(enabled); - TRACE("Set postprocessing enabled : %d", enabled); - - } - - EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView *tView, bool enabled) - { - auto view = reinterpret_cast(tView); - view->setShadowingEnabled(enabled); - } - - EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView *tView, int shadowType) - { - auto view = reinterpret_cast(tView); - view->setShadowType((ShadowType)shadowType); - } - - EMSCRIPTEN_KEEPALIVE void View_setSoftShadowOptions(TView *tView, float penumbraScale, float penumbraRatioScale) - { - auto view = reinterpret_cast(tView); - SoftShadowOptions opts; - opts.penumbraRatioScale = penumbraRatioScale; - opts.penumbraScale = penumbraScale; - view->setSoftShadowOptions(opts); - } - - EMSCRIPTEN_KEEPALIVE void View_setBloom(TView *tView, bool enabled, float strength) - { - auto view = reinterpret_cast(tView); -#ifndef __EMSCRIPTEN__ - decltype(view->getBloomOptions()) opts; - opts.enabled = enabled; - opts.strength = strength; - TRACE("Setting bloom options {.enabled = %d, strength = %f}", enabled, strength); - view->setBloomOptions(opts); -#endif - } - - EMSCRIPTEN_KEEPALIVE void View_setColorGrading(TView *tView, TColorGrading *tColorGrading) { - auto *view = reinterpret_cast(tView); - auto *colorGrading = reinterpret_cast(tColorGrading); - view->setColorGrading(colorGrading); - } - - EMSCRIPTEN_KEEPALIVE TColorGrading *ColorGrading_create(TEngine* tEngine, TToneMapping tToneMapping) { - auto engine = reinterpret_cast(tEngine); - - ToneMapper *tm; - switch (tToneMapping) + EMSCRIPTEN_KEEPALIVE void View_setBlendMode(TView *tView, TBlendMode tBlendMode) { - case TToneMapping::ACES: - TRACE("Setting tone mapping to ACES"); - tm = new ACESToneMapper(); - break; - case TToneMapping::LINEAR: - TRACE("Setting tone mapping to Linear"); - tm = new LinearToneMapper(); - break; - case TToneMapping::FILMIC: - TRACE("Setting tone mapping to Filmic"); - tm = new FilmicToneMapper(); - break; - default: - TRACE("ERROR: Unsupported tone mapping"); - return nullptr; + auto view = reinterpret_cast(tView); + view->setBlendMode(static_cast(tBlendMode)); } - auto colorGrading = ColorGrading::Builder().toneMapper(tm).build(*engine); - - delete tm; - return reinterpret_cast(colorGrading); - } - void View_setAntiAliasing(TView *tView, bool msaa, bool fxaa, bool taa) - { - auto view = reinterpret_cast(tView); - View::MultiSampleAntiAliasingOptions multiSampleAntiAliasingOptions; - multiSampleAntiAliasingOptions.enabled = msaa; - multiSampleAntiAliasingOptions.sampleCount = 2; - view->setMultiSampleAntiAliasingOptions(multiSampleAntiAliasingOptions); - - TemporalAntiAliasingOptions taaOpts; - taaOpts.enabled = taa; - - view->setTemporalAntiAliasingOptions(taaOpts); - view->setAntiAliasing(fxaa ? AntiAliasing::FXAA : AntiAliasing::NONE); - } - - EMSCRIPTEN_KEEPALIVE void View_setLayerEnabled(TView* tView, int layer, bool enabled) { - auto view = reinterpret_cast(tView); - view->setLayerEnabled(layer, enabled); - } - - EMSCRIPTEN_KEEPALIVE void View_setCamera(TView *tView, TCamera *tCamera) { - auto view = reinterpret_cast(tView); - auto *camera = reinterpret_cast(tCamera); - view->setCamera(camera); - } - - EMSCRIPTEN_KEEPALIVE TScene* View_getScene(TView* tView) { - auto view = reinterpret_cast(tView); - return reinterpret_cast(view->getScene()); - } - - EMSCRIPTEN_KEEPALIVE TCamera* View_getCamera(TView *tView) { - auto view = reinterpret_cast(tView); - return reinterpret_cast(&(view->getCamera())); - } - - EMSCRIPTEN_KEEPALIVE void View_setStencilBufferEnabled(TView *tView, bool enabled) { - auto view = reinterpret_cast(tView); - view->setStencilBufferEnabled(enabled); - } - - EMSCRIPTEN_KEEPALIVE bool View_isStencilBufferEnabled(TView *tView) { - auto view = reinterpret_cast(tView); - return view->isStencilBufferEnabled(); - } - - - EMSCRIPTEN_KEEPALIVE void View_pick(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback) - { - auto *view = reinterpret_cast(tView); - view->pick(x, y, [=](filament::View::PickingQueryResult const &result) { - callback(requestId, utils::Entity::smuggle(result.renderable), result.depth, result.fragCoords.x, result.fragCoords.y, result.fragCoords.z); - }); - } - - EMSCRIPTEN_KEEPALIVE void View_setDitheringEnabled(TView *tView, bool enabled) { - auto *view = reinterpret_cast(tView); - if(enabled) { - view->setDithering(Dithering::TEMPORAL); - } else { - view->setDithering(Dithering::NONE); + EMSCRIPTEN_KEEPALIVE TViewport View_getViewport(TView *tView) + { + auto view = reinterpret_cast(tView); + auto &vp = view->getViewport(); + TViewport tvp; + tvp.left = vp.left; + tvp.bottom = vp.bottom; + tvp.width = vp.width; + tvp.height = vp.height; + return tvp; } - } - - EMSCRIPTEN_KEEPALIVE bool View_isDitheringEnabled(TView *tView) { - auto *view = reinterpret_cast(tView); - return view->getDithering() == Dithering::TEMPORAL; - } - EMSCRIPTEN_KEEPALIVE void View_setRenderQuality(TView *tView, TQualityLevel qualityLevel) { - auto view = reinterpret_cast(tView); - RenderQuality rq; - rq.hdrColorBuffer = (filament::QualityLevel)qualityLevel; - switch(rq.hdrColorBuffer) { + EMSCRIPTEN_KEEPALIVE void View_setViewport(TView *tView, uint32_t width, uint32_t height) + { + auto view = reinterpret_cast(tView); + view->setViewport({0, 0, width, height}); + TRACE("Set viewport to %dx%d", width, height); + } + + EMSCRIPTEN_KEEPALIVE TRenderTarget *View_getRenderTarget(TView *tView) + { + auto view = reinterpret_cast(tView); + auto tRenderTarget = reinterpret_cast(view->getRenderTarget()); + return tRenderTarget; + } + + EMSCRIPTEN_KEEPALIVE void View_setRenderTarget(TView *tView, TRenderTarget *tRenderTarget) + { + auto view = reinterpret_cast(tView); + auto renderTarget = reinterpret_cast(tRenderTarget); + view->setRenderTarget(renderTarget); + } + + EMSCRIPTEN_KEEPALIVE void View_setFrustumCullingEnabled(TView *tView, bool enabled) + { + auto view = reinterpret_cast(tView); + view->setFrustumCullingEnabled(enabled); + } + + EMSCRIPTEN_KEEPALIVE void View_setPostProcessing(TView *tView, bool enabled) + { + auto view = reinterpret_cast(tView); + view->setPostProcessingEnabled(enabled); + TRACE("Set postprocessing enabled : %d", enabled); + } + + EMSCRIPTEN_KEEPALIVE void View_setShadowsEnabled(TView *tView, bool enabled) + { + auto view = reinterpret_cast(tView); + view->setShadowingEnabled(enabled); + } + + EMSCRIPTEN_KEEPALIVE void View_setShadowType(TView *tView, int shadowType) + { + auto view = reinterpret_cast(tView); + view->setShadowType((ShadowType)shadowType); + } + + EMSCRIPTEN_KEEPALIVE void View_setSoftShadowOptions(TView *tView, float penumbraScale, float penumbraRatioScale) + { + auto view = reinterpret_cast(tView); + SoftShadowOptions opts; + opts.penumbraRatioScale = penumbraRatioScale; + opts.penumbraScale = penumbraScale; + view->setSoftShadowOptions(opts); + } + + EMSCRIPTEN_KEEPALIVE void View_setBloom(TView *tView, bool enabled, float strength) + { + auto view = reinterpret_cast(tView); +#ifndef __EMSCRIPTEN__ + decltype(view->getBloomOptions()) opts; + opts.enabled = enabled; + opts.strength = strength; + TRACE("Setting bloom options {.enabled = %d, strength = %f}", enabled, strength); + view->setBloomOptions(opts); +#endif + } + + EMSCRIPTEN_KEEPALIVE void View_setColorGrading(TView *tView, TColorGrading *tColorGrading) + { + auto *view = reinterpret_cast(tView); + auto *colorGrading = reinterpret_cast(tColorGrading); + view->setColorGrading(colorGrading); + } + + EMSCRIPTEN_KEEPALIVE TColorGrading *ColorGrading_create(TEngine *tEngine, TToneMapping tToneMapping) + { + auto engine = reinterpret_cast(tEngine); + + ToneMapper *tm; + switch (tToneMapping) + { + case TToneMapping::ACES: + TRACE("Setting tone mapping to ACES"); + tm = new ACESToneMapper(); + break; + case TToneMapping::LINEAR: + TRACE("Setting tone mapping to Linear"); + tm = new LinearToneMapper(); + break; + case TToneMapping::FILMIC: + TRACE("Setting tone mapping to Filmic"); + tm = new FilmicToneMapper(); + break; + default: + TRACE("ERROR: Unsupported tone mapping"); + return nullptr; + } + auto colorGrading = ColorGrading::Builder().toneMapper(tm).build(*engine); + + delete tm; + return reinterpret_cast(colorGrading); + } + + void View_setAntiAliasing(TView *tView, bool msaa, bool fxaa, bool taa) + { + auto view = reinterpret_cast(tView); + View::MultiSampleAntiAliasingOptions multiSampleAntiAliasingOptions; + multiSampleAntiAliasingOptions.enabled = msaa; + multiSampleAntiAliasingOptions.sampleCount = 2; + view->setMultiSampleAntiAliasingOptions(multiSampleAntiAliasingOptions); + + TemporalAntiAliasingOptions taaOpts; + taaOpts.enabled = taa; + + view->setTemporalAntiAliasingOptions(taaOpts); + view->setAntiAliasing(fxaa ? AntiAliasing::FXAA : AntiAliasing::NONE); + } + + EMSCRIPTEN_KEEPALIVE void View_setLayerEnabled(TView *tView, int layer, bool enabled) + { + auto view = reinterpret_cast(tView); + view->setLayerEnabled(layer, enabled); + } + + EMSCRIPTEN_KEEPALIVE void View_setCamera(TView *tView, TCamera *tCamera) + { + auto view = reinterpret_cast(tView); + auto *camera = reinterpret_cast(tCamera); + view->setCamera(camera); + } + + EMSCRIPTEN_KEEPALIVE TScene *View_getScene(TView *tView) + { + auto view = reinterpret_cast(tView); + return reinterpret_cast(view->getScene()); + } + + EMSCRIPTEN_KEEPALIVE TCamera *View_getCamera(TView *tView) + { + auto view = reinterpret_cast(tView); + return reinterpret_cast(&(view->getCamera())); + } + + EMSCRIPTEN_KEEPALIVE void View_setStencilBufferEnabled(TView *tView, bool enabled) + { + auto view = reinterpret_cast(tView); + view->setStencilBufferEnabled(enabled); + } + + EMSCRIPTEN_KEEPALIVE bool View_isStencilBufferEnabled(TView *tView) + { + auto view = reinterpret_cast(tView); + return view->isStencilBufferEnabled(); + } + + EMSCRIPTEN_KEEPALIVE void View_pick(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback) + { + auto *view = reinterpret_cast(tView); + view->pick(x, y, [=](filament::View::PickingQueryResult const &result) + { callback(requestId, utils::Entity::smuggle(result.renderable), result.depth, result.fragCoords.x, result.fragCoords.y, result.fragCoords.z); }); + } + + EMSCRIPTEN_KEEPALIVE void View_setDitheringEnabled(TView *tView, bool enabled) + { + auto *view = reinterpret_cast(tView); + if (enabled) + { + view->setDithering(Dithering::TEMPORAL); + } + else + { + view->setDithering(Dithering::NONE); + } + } + + EMSCRIPTEN_KEEPALIVE bool View_isDitheringEnabled(TView *tView) + { + auto *view = reinterpret_cast(tView); + return view->getDithering() == Dithering::TEMPORAL; + } + + EMSCRIPTEN_KEEPALIVE void View_setRenderQuality(TView *tView, TQualityLevel qualityLevel) + { + auto view = reinterpret_cast(tView); + RenderQuality rq; + rq.hdrColorBuffer = (filament::QualityLevel)qualityLevel; + switch (rq.hdrColorBuffer) + { case filament::QualityLevel::LOW: TRACE("Render Quality: LOW"); break; @@ -224,24 +239,48 @@ using namespace filament; case filament::QualityLevel::ULTRA: TRACE("Render Quality: ULTRA"); break; + } + + view->setRenderQuality(rq); } + + EMSCRIPTEN_KEEPALIVE void View_setScene(TView *tView, TScene *tScene) + { + auto *view = reinterpret_cast(tView); + auto *scene = reinterpret_cast(tScene); + view->setScene(scene); + } + + EMSCRIPTEN_KEEPALIVE void View_setFrontFaceWindingInverted(TView *tView, bool inverted) + { + auto *view = reinterpret_cast(tView); + view->setFrontFaceWindingInverted(inverted); + } + + EMSCRIPTEN_KEEPALIVE void View_setFogOptions(TView *tView, TFogOptions *tFogOptions) + { + auto view = reinterpret_cast(tView); + FogOptions fogOptions { + .distance = tFogOptions->distance, + .cutOffDistance = tFogOptions->cutOffDistance, + .maximumOpacity = tFogOptions->maximumOpacity, + .height = tFogOptions->height, + .heightFalloff = tFogOptions->heightFalloff, + .color = LinearColor(tFogOptions->linearColor.x, tFogOptions->linearColor.y, tFogOptions->linearColor.z), + .density = tFogOptions->density, + .inScatteringStart = tFogOptions->inScatteringStart, + .inScatteringSize = tFogOptions->inScatteringSize, + .fogColorFromIbl = tFogOptions->fogColorFromIbl, + .skyColor = reinterpret_cast(tFogOptions->skyColor), + .enabled = tFogOptions->enabled + }; + - view->setRenderQuality(rq); - } - - EMSCRIPTEN_KEEPALIVE void View_setScene(TView *tView, TScene *tScene) { - auto *view = reinterpret_cast(tView); - auto *scene = reinterpret_cast(tScene); - view->setScene(scene); - } - - EMSCRIPTEN_KEEPALIVE void View_setFrontFaceWindingInverted(TView *tView, bool inverted) { - auto *view = reinterpret_cast(tView); - view->setFrontFaceWindingInverted(inverted); - } - + TRACE("Setting fog enabled to %d (tFogOptions->cutOffDistance %f)", fogOptions.enabled, tFogOptions->cutOffDistance); + view->setFogOptions(fogOptions); + } #ifdef __cplusplus -} + } } #endif diff --git a/thermion_dart/test/view_tests.dart b/thermion_dart/test/view_tests.dart index e08eaa70..81b7a8a7 100644 --- a/thermion_dart/test/view_tests.dart +++ b/thermion_dart/test/view_tests.dart @@ -179,7 +179,7 @@ void main() async { type: LightType.SUN, color: 6500, intensity: 100000000, - direction: Vector3(0,0,-1), + direction: Vector3(0, 0, -1), position: Vector3.zero())); await scene.addEntity(light); @@ -188,7 +188,7 @@ void main() async { await materialInstance2.setParameterTexture("baseColorMap", texture, await FilamentApp.instance!.createTextureSampler()); - await materialInstance2.setParameterInt("baseColorIndex",0); + await materialInstance2.setParameterInt("baseColorIndex", 0); await materialInstance2.setParameterFloat4("baseColorFactor", 1, 1, 1, 1); await cube.setMaterialInstanceAt(materialInstance2 as FFIMaterialInstance); @@ -259,7 +259,7 @@ void main() async { type: LightType.SUN, color: 6500, intensity: 100000000, - direction: Vector3(0,0,-1), + direction: Vector3(0, 0, -1), position: Vector3.zero())); await scene.addEntity(light); @@ -268,7 +268,7 @@ void main() async { await materialInstance2.setParameterTexture("baseColorMap", texture, await FilamentApp.instance!.createTextureSampler()); - await materialInstance2.setParameterInt("baseColorIndex",0); + await materialInstance2.setParameterInt("baseColorIndex", 0); await materialInstance2.setParameterFloat4("baseColorFactor", 1, 1, 1, 1); await cube.setMaterialInstanceAt(materialInstance2 as FFIMaterialInstance); @@ -281,6 +281,24 @@ void main() async { p.join(testHelper.outDir.path, "render_target_as_texture.bmp"), isFloat: true); }); + + test('fog tests', () async { + await testHelper.withViewer((viewer) async { + var cube = await FilamentApp.instance! + .createGeometry(GeometryHelper.cube(flipUvs: true), nullptr); + await viewer.addToScene(cube); + + final camera = await viewer.getActiveCamera(); + await camera.lookAt(Vector3(1, 3, 5), focus: Vector3.zero()); + + await testHelper.capture(viewer.view, "fog_options_disabled"); + + await viewer.view.setFogOptions(FogOptions( + enabled: true, distance: 0, density: 0.5)); + await testHelper.capture(viewer.view, "fog_options_enabled"); + + }, addSkybox: true, postProcessing: true); + }); } // test('one swapchain, render view to render target', () async {