diff --git a/materials/capture_uv.mat b/materials/capture_uv.mat index bda2c47d..a44f7f66 100644 --- a/materials/capture_uv.mat +++ b/materials/capture_uv.mat @@ -100,8 +100,8 @@ fragment { //material.baseColor = vec4(sampledDepth.r, 0.0, 0.0, 1.0); //material.baseColor = vec4(vertexDepth, 0.0, 0.0, 1.0); - if(materialParams.useDepth && abs(vertexDepth - sampledDepth.r) > 0.001) { - discard; + if(materialParams.useDepth && (sampledDepth.r < 0.0001 || abs(vertexDepth - sampledDepth.r) > 0.001)) { + material.baseColor = vec4(0.0, 0.0, 0.0, 0.0); } else { vec2 texSize = vec2(textureSize(materialParams_color, 0)); vec4 color = textureLod(materialParams_color, uvToRenderTargetUV(deviceCoords.xy), 0.0f); diff --git a/materials/vdtm.mat b/materials/vdtm.mat index e00c7e90..a0720a26 100644 --- a/materials/vdtm.mat +++ b/materials/vdtm.mat @@ -8,7 +8,7 @@ material { }, { type : float3[3], - name : cameraPositions + name : cameraForwardVectors }, { type : bool, @@ -17,8 +17,8 @@ material { ], variables : [ { - type : float3, - name : blendWeights, + type : float, + name : samplerCoord, } ], requires : [ position, uv0 ], @@ -43,42 +43,57 @@ material { // Parameters: // - perspectives: 3D texture containing different perspective views of the object // - cameraPositions: Array of camera positions used to render each perspective slice - vertex { void materialVertex(inout MaterialVertexInputs material) { - vec3 worldCameraPos = getWorldCameraPosition(); - vec4 currentCameraPos = getUserWorldFromWorldMatrix() * vec4(worldCameraPos, 1.0); + vec3 forward = -(normalize(getWorldFromViewMatrix()[2].xyz)); + + vec3 weights = vec3(0.0, 0.0, 0.0); + int idxMax = 0; + float weightMax = 0.0; + for(int i = 0; i < 3; i++) { + weights[i] = dot(forward, materialParams.cameraForwardVectors[i]); + if(weights[i] > weightMax) { + weightMax = weights[i]; + idxMax = i; + } + } + + if(idxMax == 0) { + float z = (weights.y * 0.5) + (weights.z * 1.0); + } + + //weights /= (weights.x + weights.y + weights.z); - material.blendWeights.xyz = vec3(0.0f); - float totalWeight = 0.0; - - for (int i = 0; i < 3; i++) { - vec3 cameraPos = materialParams.cameraPositions[i]; - float dist = distance(currentCameraPos.xyz, cameraPos); - material.blendWeights[i] = exp(-dist); - totalWeight += material.blendWeights[i]; - } - if (totalWeight > 0.0) { - material.blendWeights /= totalWeight; - } - //material.blendWeights.x = exp(-distance(currentCameraPos.xyz, materialParams.cameraPositions[0])); + + material.samplerCoord.x = z; } } fragment { + void useMax(vec3 forward) { + float maxIdx = 0.0f; + float maxWeight = 0.0f; + for(int i =0; i < 3; i++) { + float weight = dot(forward, materialParams.cameraForwardVectors[i]); + if(weight > maxWeight) { + maxWeight = weight; + maxIdx = float(i) / 2.0f; + } + } + + float z = maxIdx; + + } void material(inout MaterialInputs material) { prepareMaterial(material); - - vec3 weights = variable_blendWeights.xyz; - - float z = (weights.x * 0.0) + (weights.y * 0.5) + (weights.z * 1.0); vec2 uv = getUV0(); if(materialParams.flipUVs) { uv = uvToRenderTargetUV(uv); } - vec3 texCoord = vec3(uv, z); + vec3 texCoord = vec3(uv, variable_samplerCoord.x); material.baseColor = texture(materialParams_perspectives, texCoord); + } } \ No newline at end of file diff --git a/thermion_dart/test/asset_tests.dart b/thermion_dart/test/asset_tests.dart index 270bf541..9093f587 100644 --- a/thermion_dart/test/asset_tests.dart +++ b/thermion_dart/test/asset_tests.dart @@ -9,24 +9,28 @@ void main() async { group("assets", () { test('load/clear skybox', () async { await testHelper.withViewer((viewer) async { - final camera = await viewer.getActiveCamera(); - print(await camera.getModelMatrix()); - print(await camera.getViewMatrix()); - print(await camera.getProjectionMatrix()); - await camera.lookAt(Vector3(0, 0, 10), - focus: Vector3.zero(), up: Vector3(0, 1, 0)); await viewer.loadSkybox( "file://${testHelper.testDir}/assets/default_env_skybox.ktx"); await testHelper.capture(viewer.view, "load_skybox"); await viewer.removeSkybox(); await testHelper.capture(viewer.view, "remove_skybox"); - }); + + await viewer.setPostProcessing(true); + await viewer.setBloom(false, 0.01); + await viewer.loadSkybox( + "file://${testHelper.testDir}/assets/default_env_skybox.ktx"); + await testHelper.capture( + viewer.view, "load_skybox_with_postprocessing"); + await viewer.removeSkybox(); + await testHelper.capture( + viewer.view, "remove_skybox_with_postprocessing"); + }, createRenderTarget: true); }); test('load/remove ibl', () async { await testHelper.withViewer((viewer) async { var asset = await viewer - .loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + .loadGltf("file://${testHelper.testDir}/assets/cube.glb"); await viewer .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); await testHelper.capture(viewer.view, "ibl_loaded"); @@ -37,8 +41,9 @@ void main() async { test('load/remove gltf', () async { await testHelper.withViewer((viewer) async { - var asset = await viewer - .loadGlb("file://${testHelper.testDir}/assets/cube.gltf", relativeResourcePath: "${testHelper.testDir}/assets"); + var asset = await viewer.loadGltf( + "file://${testHelper.testDir}/assets/cube.gltf", + relativeResourcePath: "${testHelper.testDir}/assets"); await viewer .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); await testHelper.capture(viewer.view, "gltf_loaded"); @@ -47,10 +52,26 @@ void main() async { }, cameraPosition: Vector3(0, 0, 5)); }); + test('transform gltf to unit cube', () async { + await testHelper.withViewer((viewer) async { + var asset = await viewer.loadGltf( + "file://${testHelper.testDir}/assets/cube.gltf", + relativeResourcePath: "${testHelper.testDir}/assets"); + + await viewer + .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); + await asset.setTransform(Matrix4.compose( + Vector3.zero(), Quaternion.identity(), Vector3.all(2))); + await testHelper.capture(viewer.view, "gltf_before_unit_cube"); + await asset.transformToUnitCube(); + await testHelper.capture(viewer.view, "gltf_after_unit_cube"); + }, cameraPosition: Vector3(0, 0, 5)); + }); + test('add/remove asset from scene ', () async { await testHelper.withViewer((viewer) async { var asset = await viewer - .loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + .loadGltf("file://${testHelper.testDir}/assets/cube.glb"); await viewer .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); await testHelper.capture(viewer.view, "asset_added"); @@ -62,7 +83,7 @@ void main() async { test('destroy assets', () async { await testHelper.withViewer((viewer) async { var asset = await viewer - .loadGlb("file://${testHelper.testDir}/assets/cube.glb"); + .loadGltf("file://${testHelper.testDir}/assets/cube.glb"); await viewer .loadIbl("file://${testHelper.testDir}/assets/default_env_ibl.ktx"); await testHelper.capture(viewer.view, "assets_present"); @@ -70,6 +91,5 @@ void main() async { await testHelper.capture(viewer.view, "assets_destroyed"); }, cameraPosition: Vector3(0, 0, 5)); }); - }); } diff --git a/thermion_dart/test/assets/cube_texture2.svg b/thermion_dart/test/assets/cube_texture2.svg new file mode 100644 index 00000000..3d5282bd --- /dev/null +++ b/thermion_dart/test/assets/cube_texture2.svg @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + Front + + + Back + + + Top + + + Bottom + + + Right + + + Left + diff --git a/thermion_dart/test/assets/cube_texture2_512x512.png b/thermion_dart/test/assets/cube_texture2_512x512.png new file mode 100644 index 00000000..e3890053 Binary files /dev/null and b/thermion_dart/test/assets/cube_texture2_512x512.png differ diff --git a/thermion_dart/test/assets/cube_texture2_512x512_flipped.png b/thermion_dart/test/assets/cube_texture2_512x512_flipped.png new file mode 100644 index 00000000..9c1fa5c7 Binary files /dev/null and b/thermion_dart/test/assets/cube_texture2_512x512_flipped.png differ diff --git a/thermion_dart/test/depth_tests.dart b/thermion_dart/test/depth_tests.dart new file mode 100644 index 00000000..fafe4d1b --- /dev/null +++ b/thermion_dart/test/depth_tests.dart @@ -0,0 +1,392 @@ +@Timeout(const Duration(seconds: 600)) +import 'dart:async'; +import 'dart:io'; +import 'dart:math'; +import 'dart:typed_data'; +import 'package:test/test.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_camera.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_view.dart'; +import 'package:thermion_dart/thermion_dart.dart'; +import 'helpers.dart'; + +void checkMinMaxPixelValues(Float32List pixelBuffer, int width, int height) { + var minVal = 99999.0; + var maxVal = 0.0; + for (var y = 0; y < height; y++) { + for (var x = 0; x < width; x++) { + for (int i = 0; i < 3; i++) { + final srcIndex = (y * width * 4) + (x * 4) + i; + if (pixelBuffer[srcIndex] == 0) { + continue; + } + minVal = min(minVal, pixelBuffer[srcIndex]); + maxVal = max(maxVal, pixelBuffer[srcIndex]); + } + } + } + print("minVal $minVal maxVal $maxVal"); +} + +void main() async { + final testHelper = TestHelper("depth"); + await testHelper.setup(); + + test('write depth value to R32F texture', () async { + final viewportDimensions = (width: 512, height: 512); + var swapChain = await FilamentApp.instance!.createHeadlessSwapChain( + viewportDimensions.width, viewportDimensions.height) as FFISwapChain; + + var color = await FilamentApp.instance! + .createTexture(viewportDimensions.width, viewportDimensions.height, + flags: { + TextureUsage.TEXTURE_USAGE_BLIT_SRC, + TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT, + TextureUsage.TEXTURE_USAGE_SAMPLEABLE + }, + textureFormat: TextureFormat.R32F); + + var renderTarget = await FilamentApp.instance!.createRenderTarget( + viewportDimensions.width, viewportDimensions.height, color: color) + as FFIRenderTarget; + + var view = await FilamentApp.instance!.createView() as FFIView; + await view.setPostProcessing(false); + await view.setRenderTarget(renderTarget); + + await FilamentApp.instance!.setClearOptions(0.0, 1.0, 0.0, 1.0); + var scene = await FilamentApp.instance!.createScene() as FFIScene; + + await view.setScene(scene); + await view.setViewport(viewportDimensions.width, viewportDimensions.height); + final camera = FFICamera( + await withPointerCallback((cb) => + Engine_createCameraRenderThread(FilamentApp.instance!.engine, cb)), + FilamentApp.instance! as FFIFilamentApp); + + await camera.setLensProjection(); + + await view.setCamera(camera); + + await view.setFrustumCullingEnabled(false); + await camera.setLensProjection(near: 0.5, far: 10); + final dist = 2.0; + await camera.lookAt( + Vector3( + -0.5, + dist, + dist, + ), + ); + + var mat = await FilamentApp.instance!.createMaterial( + File( + "/Users/nickfisher/Documents/thermion/materials/linear_depth.filamat", + ).readAsBytesSync(), + ); + var mi = await mat.createInstance(); + await mi.setDepthCullingEnabled(true); + await mi.setDepthWriteEnabled(true); + await mi.setCullingMode(CullingMode.BACK); + + var umi = await FilamentApp.instance! + .createUbershaderMaterialInstance(unlit: true); + var cube = await FilamentApp.instance! + .createGeometry(GeometryHelper.cube(), nullptr); + await scene.add(cube as FFIAsset); + await umi.setParameterFloat4("baseColorFactor", 1, 1, 1, 0); + + await cube.setTransform( + Matrix4.compose(Vector3.zero(), Quaternion.identity(), Vector3.all(1))); + await cube.setMaterialInstanceAt(mi as FFIMaterialInstance); + await FilamentApp.instance!.register(swapChain, view); + var pixelBuffers = await testHelper.capture(null, "linear_depth", + swapChain: swapChain, pixelDataFormat: PixelDataFormat.R); + checkMinMaxPixelValues(pixelBuffers[view]!.buffer.asFloat32List(), + viewportDimensions.width, viewportDimensions.height); + }); + + test('check NDC depth value', () async { + final viewportDimensions = (width: 512, height: 512); + var swapChain = await FilamentApp.instance!.createHeadlessSwapChain( + viewportDimensions.width, viewportDimensions.height) as FFISwapChain; + + var color = await FilamentApp.instance! + .createTexture(viewportDimensions.width, viewportDimensions.height, + flags: { + TextureUsage.TEXTURE_USAGE_BLIT_SRC, + TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT, + TextureUsage.TEXTURE_USAGE_SAMPLEABLE + }, + textureFormat: TextureFormat.R32F); + + var renderTarget = await FilamentApp.instance!.createRenderTarget( + viewportDimensions.width, viewportDimensions.height, color: color) + as FFIRenderTarget; + + var view = await FilamentApp.instance!.createView() as FFIView; + await view.setPostProcessing(false); + await view.setRenderTarget(renderTarget); + + await FilamentApp.instance!.setClearOptions(0.0, 1.0, 0.0, 1.0); + var scene = await FilamentApp.instance!.createScene() as FFIScene; + + await view.setScene(scene); + await view.setViewport(viewportDimensions.width, viewportDimensions.height); + final camera = FFICamera( + await withPointerCallback((cb) => + Engine_createCameraRenderThread(FilamentApp.instance!.engine, cb)), + FilamentApp.instance! as FFIFilamentApp); + + await camera.setLensProjection(); + + await view.setCamera(camera); + + await view.setFrustumCullingEnabled(false); + await camera.setLensProjection(near: 0.5, far: 10); + final dist = 3.0; + await camera.lookAt( + Vector3( + -0.5, + dist, + dist, + ), + ); + + var mat = await FilamentApp.instance!.createMaterial( + File( + "/Users/nickfisher/Documents/thermion/materials/ndc_depth.filamat", + ).readAsBytesSync(), + ); + var mi = await mat.createInstance(); + await mi.setDepthCullingEnabled(true); + await mi.setDepthWriteEnabled(true); + await mi.setCullingMode(CullingMode.BACK); + + var umi = await FilamentApp.instance! + .createUbershaderMaterialInstance(unlit: true); + var cube = await FilamentApp.instance! + .createGeometry(GeometryHelper.cube(), nullptr); + await scene.add(cube as FFIAsset); + await umi.setParameterFloat4("baseColorFactor", 1, 1, 1, 0); + + await cube.setTransform( + Matrix4.compose(Vector3.zero(), Quaternion.identity(), Vector3.all(1))); + await cube.setMaterialInstanceAt(mi as FFIMaterialInstance); + await FilamentApp.instance!.register(swapChain, view); + var pixelBuffers = await testHelper.capture(null, "ndc_depth", + swapChain: swapChain, pixelDataFormat: PixelDataFormat.R); + checkMinMaxPixelValues(pixelBuffers[view]!.buffer.asFloat32List(), + viewportDimensions.width, viewportDimensions.height); + }); + + group('depth sampling', () { + test("depth sampling", () async { + await testHelper.withViewer((viewer) async { + await FilamentApp.instance!.setClearOptions(0, 0, 0, 1, + clearStencil: 0, discard: false, clear: true); + final camera = await viewer.getActiveCamera(); + await camera.lookAt(Vector3(3, 3, 6)); + + final view = await testHelper.createView(testHelper.swapChain); + await testHelper.withCube( + viewer, + (cube) async { + var mat = await FilamentApp.instance!.createMaterial( + File( + "/Users/nickfisher/Documents/thermion/materials/depth_sampler.filamat", + ).readAsBytesSync(), + ); + final mi = await mat.createInstance(); + + await viewer.addToScene(cube); + final secondScene = await view.getScene(); + await secondScene.add(cube); + + final sampler = await FilamentApp.instance!.createTextureSampler(); + final rt = await view.getRenderTarget(); + final color = await rt!.getColorTexture(); + final depth = await rt!.getDepthTexture(); + await mi.setParameterTexture( + "depth", + depth, + await FilamentApp.instance!.createTextureSampler( + compareMode: TextureCompareMode.COMPARE_TO_TEXTURE, + ), + ); + await cube.setMaterialInstanceAt(mi); + + await testHelper.capture(null, "depth_sampling1"); + }, + ); + }, createRenderTarget: true); + }); + }); +} + + + // group('projection', () { + // test('project texture & UV unwrap', () async { + // await testHelper.withViewer((viewer) async { + // final camera = await viewer.getActiveCamera(); + // await viewer.view.setFrustumCullingEnabled(false); + // await camera.setLensProjection(near: 0.01, far: 100); + // final dist = 26.0; + // await camera.lookAt( + // Vector3( + // -0.5, + // dist, + // dist, + // ), + // ); + // await FilamentApp.instance! + // .unregister(testHelper.swapChain, viewer.view); + + // await withView(testHelper.swapChain, viewer, (linearDepthView) async { + // await withView(testHelper.swapChain, viewer, (manualDepthView) async { + // await manualDepthView.setRenderOrder(1); + // await linearDepthView.setRenderOrder(0); + + // await viewer.view.setRenderOrder(2); + // await withManualDepthMaterial(testHelper, viewer, ( + // manualDepthMi, + // ) async { + // await withSampledDepthMaterial(testHelper, viewer, ( + // sampledDepthMi, + // ) async { + // await sampledDepthMi.setParameterTexture( + // "depth", + // await (await manualDepthView.getRenderTarget())! + // .getColorTexture(), + // await FilamentApp.instance!.createTextureSampler()); + + // await withLinearDepthMaterial(testHelper, viewer, ( + // linearDepthMi, + // ) async { + // await withProjectionMaterial(testHelper, viewer, ( + // projectMi, + // ) async { + // await FilamentApp.instance!.setClearOptions(0, 0, 0, 1, + // clearStencil: 0, discard: false, clear: true); + // await testHelper.withCube(viewer, (cube2) async { + // var ubershader = await cube2.getMaterialInstanceAt(); + // (await manualDepthView.getScene()).remove(cube2); + // await ubershader.setParameterFloat4( + // "baseColorFactor", 0.0, 1.0, 0.0, 1.0); + // await cube2.setTransform(Matrix4.compose( + // Vector3(-0.5, 0, -0.5), + // Quaternion.identity(), + // Vector3.all(1))); + // await testHelper.withCube(viewer, (cube) async { + // await cube.setTransform(Matrix4.compose(Vector3.zero(), + // Quaternion.identity(), Vector3.all(1))); + // var divisions = 1; + // var ubershader = await cube.getMaterialInstanceAt(); + // await ubershader.setDepthCullingEnabled(true); + // await ubershader.setDepthWriteEnabled(true); + // await ubershader.setCullingMode(CullingMode.BACK); + // await ubershader.setParameterInt("baseColorIndex", 0); + + // await ubershader.setParameterTexture( + // "baseColorMap", + // await createTextureFromImage(testHelper), + // await FilamentApp.instance!.createTextureSampler()); + + // // final color = await (await linearDepthView.getRenderTarget())! + // // .getColorTexture(); + // // final depth = await (await manualDepthView.getRenderTarget())! + // // .getColorTexture(); + + // // await projectMi.setParameterTexture("color", color, + // // await FilamentApp.instance!.createTextureSampler()); + // // await projectMi.setParameterTexture("depth", depth, + // // await FilamentApp.instance!.createTextureSampler()); + // // await projectMi.setDepthCullingEnabled(true); + // // await projectMi.setParameterBool("useDepth", true); + + // // for (int i = 0; i < divisions; i++) { + // // await camera.lookAt( + // // Vector3( + // // sin(i / divisions * pi) * dist, + // // dist, + // // cos(i / divisions * pi) * dist, + // // ), + // // ); + // // await cube.setMaterialInstanceAt(manualDepthMi); + + // var pixelBuffers = await testHelper + // .capture(null, "project_texture_color", + // beforeRender: (view) async { + // if (view == linearDepthView) { + // await cube.setMaterialInstanceAt(linearDepthMi); + // } else if (view == manualDepthView) { + // await cube.setMaterialInstanceAt(manualDepthMi); + // } else { + // throw Exception(); + // } + // }); + // // var comparison = comparePixelBuffers( + // // pixelBuffers[1], pixelBuffers[2], 512, 512); + // // savePixelBufferToBmp(comparison, 512, 512, "cmparison"); + // // await cube.setMaterialInstanceAt(ubershader); + // checkRedFromRGBAPixelBuffer( + // pixelBuffers[manualDepthView]! + // .buffer + // .asFloat32List(), + // 512, + // 512); + // // } + // }); + // }); + // }); + // }); + // }); + // }); + // }); + // }); + // }, createRenderTarget: true); + // }); + // }); +// } + +// final projectedImage = await viewer.createImage(512, 512, 4); +// final data = await projectedImage.getData(); +// data.setRange(0, data.length, floatPixelBuffer); +// final projectedTexture = await FilamentApp.instance!.createTexture( +// 512, +// 512, +// textureFormat: TextureFormat.RGBA32F, +// ); +// await projectedTexture.setLinearImage( +// projectedImage, +// PixelDataFormat.RGBA, +// PixelDataType.FLOAT, +// ); + +// await ubershader.setParameterTexture( +// "baseColorMap", +// projectedTexture, +// sampler, +// ); +// await object.setMaterialInstanceAt(ubershader); +// await testHelper.capture( +// viewer, +// "retextured_${key}_$i", +// renderTarget: rt, +// ); +// await resetMaterial(); +// } +// await viewer.destroyAsset(object); +// } +// }); +// }); +// }); +// }); +// }); +// } diff --git a/thermion_dart/test/postprocessing_tests.dart b/thermion_dart/test/postprocessing_tests.dart new file mode 100644 index 00000000..0f38b59b --- /dev/null +++ b/thermion_dart/test/postprocessing_tests.dart @@ -0,0 +1,40 @@ +@Timeout(const Duration(seconds: 600)) +import 'package:test/test.dart'; +import 'package:thermion_dart/src/filament/src/light_options.dart'; +import 'package:thermion_dart/thermion_dart.dart'; + +import 'helpers.dart'; + +void main() async { + final testHelper = TestHelper("postprocessing"); + await testHelper.setup(); + group("assets", () { + test('enable/disable postprocessing', () async { + await testHelper.withViewer((viewer) async { + await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0); + await testHelper.capture(viewer.view, "empty_scene_no_postprocessing"); + await viewer.setPostProcessing(true); + await testHelper.capture(viewer.view, "empty_scene_postprocessing"); + }, postProcessing: false, createRenderTarget: true); + }); + + test('bloom', () async { + await testHelper.withViewer((viewer) async { + await FilamentApp.instance!.setClearOptions(1, 1, 1, 1, clear: false); + var asset = await viewer + .loadGltf("file://${testHelper.testDir}/assets/cube.glb"); + var light = await viewer.addDirectLight( + DirectLight.point(intensity: 1000000, falloffRadius: 10)); + await viewer.setLightPosition(light, 1, 2, 2); + await viewer.setBloom(false, 0.5); + await testHelper.capture(viewer.view, "postprocessing_no_bloom"); + await viewer.setBloom(true, 0.5); + await testHelper.capture(viewer.view, "postprocessing_bloom_0.5"); + await viewer.setBloom(true, 1.0); + await testHelper.capture(viewer.view, "postprocessing_bloom_1.0"); + }, postProcessing: true, createRenderTarget: true, bg: kBlue); + }); + + + }); +}