From cac063324d15a9dee6bacd76f523433f61dc4dcd Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Tue, 25 Mar 2025 12:16:38 +0800 Subject: [PATCH] texture projection work --- .../lib/src/utils/src/texture_projection.dart | 71 ++++++++++++------ thermion_dart/test/projection_tests.dart | 75 +++++-------------- 2 files changed, 66 insertions(+), 80 deletions(-) diff --git a/thermion_dart/lib/src/utils/src/texture_projection.dart b/thermion_dart/lib/src/utils/src/texture_projection.dart index b6850335..308a155d 100644 --- a/thermion_dart/lib/src/utils/src/texture_projection.dart +++ b/thermion_dart/lib/src/utils/src/texture_projection.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'dart:typed_data'; 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_view.dart'; import 'package:thermion_dart/thermion_dart.dart'; @@ -12,6 +13,7 @@ class TextureProjection { final Material depthWriteMaterial; final MaterialInstance depthWriteMaterialInstance; final Texture texture; + final View sourceView; final View depthView; final View projectionView; @@ -22,6 +24,7 @@ class TextureProjection { required this.depthWriteMaterial, required this.depthWriteMaterialInstance, required this.texture, + required this.sourceView, required this.depthView, required this.projectionView}) {} @@ -39,9 +42,23 @@ class TextureProjection { await depthWriteView.setFrustumCullingEnabled(false); await depthWriteView.setPostProcessing(false); await depthWriteView.setViewport(viewport.width, viewport.height); - await depthWriteView.setBlendMode(BlendMode.opaque); + final depthWriteColorTexture = await FilamentApp.instance! + .createTexture(viewport.width, viewport.height, + flags: { + TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT, + TextureUsage.TEXTURE_USAGE_SAMPLEABLE, + TextureUsage.TEXTURE_USAGE_BLIT_SRC + }, + textureFormat: TextureFormat.R32F); + await depthWriteView + .setRenderTarget(await FilamentApp.instance!.createRenderTarget( + viewport.width, + viewport.height, + color: depthWriteColorTexture, + ) as FFIRenderTarget); + final color = await (await sourceView.getRenderTarget())!.getColorTexture(); final depth = await (await depthWriteView.getRenderTarget())!.getColorTexture(); @@ -64,25 +81,11 @@ class TextureProjection { await projectionView.setPostProcessing(false); await projectionView.setViewport(viewport.width, viewport.height); - final depthWriteColorTexture = await FilamentApp.instance! - .createTexture(viewport.width, viewport.height, - flags: { - TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT, - TextureUsage.TEXTURE_USAGE_SAMPLEABLE, - TextureUsage.TEXTURE_USAGE_BLIT_SRC - }, - textureFormat: TextureFormat.R32F); - await depthWriteView - .setRenderTarget(await FilamentApp.instance!.createRenderTarget( - viewport.width, - viewport.height, - color: depthWriteColorTexture, - ) as FFIRenderTarget); - await FilamentApp.instance!.register(swapChain, depthWriteView); await FilamentApp.instance!.register(swapChain, projectionView); return TextureProjection._( + sourceView: sourceView, swapChain: swapChain, depthView: depthWriteView, projectionView: projectionView, @@ -100,19 +103,43 @@ class TextureProjection { await FilamentApp.instance!.destroyView(projectionView); } - Future execute(ThermionAsset target, View view) async { + var _pixelBuffers = {}; + + Uint8List getDepthWritePixelBuffer() => _pixelBuffers[depthView]!; + Uint8List getProjectedPixelBuffer() => _pixelBuffers[projectionView]!; + + Future project(ThermionAsset target) async { + final camera = await sourceView.getCamera(); + await depthView.setCamera(camera); + await projectionView.setCamera(camera); + await (depthView as FFIView) + .setScene(await sourceView.getScene() as FFIScene); + await (projectionView as FFIView) + .setScene(await sourceView.getScene() as FFIScene); + + await sourceView.setRenderOrder(0); + await depthView.setRenderOrder(1); + await projectionView.setRenderOrder(2); + var originalMi = await target.getMaterialInstanceAt(); - var pixelBuffers = await FilamentApp.instance! - .capture(swapChain, view: view, beforeRender: (view) async { + + var pixelBuffers = await FilamentApp.instance!.capture(swapChain, + beforeRender: (view) async { if (view == depthView) { await target.setMaterialInstanceAt(depthWriteMaterialInstance); } else if (view == projectionView) { await target.setMaterialInstanceAt(projectionMaterialInstance); } }, - pixelDataFormat: PixelDataFormat.RGBA, - pixelDataType: PixelDataType.FLOAT); + pixelDataFormat: PixelDataFormat.RGBA, + pixelDataType: PixelDataType.FLOAT); + await target.setMaterialInstanceAt(originalMi); - return pixelBuffers.firstWhere((pb) => pb.$1 == projectionView).$2; + + _pixelBuffers.clear(); + + for (final (view, pixelBuffer) in pixelBuffers) { + _pixelBuffers[view] = pixelBuffer; + } } } diff --git a/thermion_dart/test/projection_tests.dart b/thermion_dart/test/projection_tests.dart index ef752852..d1051a9a 100644 --- a/thermion_dart/test/projection_tests.dart +++ b/thermion_dart/test/projection_tests.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'dart:io'; import 'dart:math'; import 'package:test/test.dart'; +import 'package:thermion_dart/src/utils/src/texture_projection.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'; @@ -60,49 +61,13 @@ void main() async { final cube = await _makeCube(testHelper, viewer); final ubershader = await cube.getMaterialInstanceAt(); final originalTexture = await createTextureFromImage(testHelper); - final sampler = - await FilamentApp.instance!.createTextureSampler(); + final sampler = await FilamentApp.instance!.createTextureSampler(); - await ubershader.setParameterTexture("baseColorMap", originalTexture, - sampler); + await ubershader.setParameterTexture( + "baseColorMap", originalTexture, sampler); - final depthWriteView = await testHelper.createView(testHelper.swapChain, - textureFormat: TextureFormat.R32F); - final captureView = await testHelper.createView(testHelper.swapChain); - await viewer.view.setRenderOrder(0); - await depthWriteView.setRenderOrder(1); - await captureView.setRenderOrder(2); - - for (var view in [captureView, depthWriteView]) { - await view.setCamera(camera); - await (view as FFIView) - .setScene(await viewer.view.getScene() as FFIScene); - } - - var depthWriteMat = await FilamentApp.instance!.createMaterial( - File( - "/Users/nickfisher/Documents/thermion/materials/linear_depth.filamat", - ).readAsBytesSync(), - ); - var depthWriteMi = await depthWriteMat.createInstance(); - - var captureMat = await FilamentApp.instance!.createMaterial( - File( - "/Users/nickfisher/Documents/thermion/materials/capture_uv.filamat", - ).readAsBytesSync(), - ); - var captureMi = await captureMat.createInstance(); - - final color = - await (await viewer.view.getRenderTarget())!.getColorTexture(); - final depth = - await (await depthWriteView.getRenderTarget())!.getColorTexture(); - await captureMi.setParameterBool("flipUVs", true); - await captureMi.setParameterTexture( - "color", color, await FilamentApp.instance!.createTextureSampler()); - await captureMi.setParameterTexture( - "depth", depth, await FilamentApp.instance!.createTextureSampler()); - await captureMi.setParameterBool("useDepth", true); + var textureProjection = + await TextureProjection.create(viewer.view, testHelper.swapChain); await FilamentApp.instance!.setClearOptions(0, 0, 0, 1, clearStencil: 0, discard: false, clear: true); @@ -115,7 +80,7 @@ void main() async { 512, textureFormat: TextureFormat.RGBA32F, ); - + for (int i = 0; i < divisions; i++) { await camera.lookAt( Vector3( @@ -125,23 +90,17 @@ void main() async { ), ); - var pixelBuffers = await testHelper.capture(null, "capture_uv_$i", - beforeRender: (view) async { - if (view == viewer.view) { - await ubershader.setParameterTexture("baseColorMap", originalTexture, - sampler); - await cube.setMaterialInstanceAt(ubershader); - } else if (view == depthWriteView) { - await cube.setMaterialInstanceAt(depthWriteMi); - } else if (view == captureView) { - await cube.setMaterialInstanceAt(captureMi); - } - }); + await textureProjection.project(cube); + final depth = textureProjection.getDepthWritePixelBuffer(); + await savePixelBufferToBmp( + depth, 512, 512, "${testHelper.outDir.path}/depth_$i.bmp"); + final projected = textureProjection.getProjectedPixelBuffer(); + await savePixelBufferToBmp( + depth, 512, 512, "${testHelper.outDir.path}/projected_$i.bmp"); await cube.setMaterialInstanceAt(ubershader); final data = await projectedImage.getData(); - data.setRange(0, data.length, - pixelBuffers[captureView]!.buffer.asFloat32List()); + data.setRange(0, data.length, projected.buffer.asFloat32List()); await projectedTexture.setLinearImage( projectedImage, @@ -157,8 +116,8 @@ void main() async { await testHelper.capture(viewer.view, "capture_uv_retextured_$i"); - await ubershader.setParameterTexture("baseColorMap", originalTexture, - sampler); + await ubershader.setParameterTexture( + "baseColorMap", originalTexture, sampler); } }, createRenderTarget: true); });