VDTM tests
This commit is contained in:
328
thermion_dart/test/view_dependent_texture_mapping_tests.dart
Normal file
328
thermion_dart/test/view_dependent_texture_mapping_tests.dart
Normal file
@@ -0,0 +1,328 @@
|
||||
@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/utils/src/texture_projection.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'helpers.dart';
|
||||
|
||||
Future<(LinearImage, Texture, TextureSampler)> createTextureFromImage(
|
||||
TestHelper testHelper) async {
|
||||
final image = await FilamentApp.instance!.decodeImage(
|
||||
File("${testHelper.testDir}/assets/cube_texture2_512x512.png")
|
||||
.readAsBytesSync());
|
||||
final texture = await FilamentApp.instance!
|
||||
.createTexture(await image.getWidth(), await image.getHeight());
|
||||
await texture.setLinearImage(
|
||||
image, PixelDataFormat.RGBA, PixelDataType.FLOAT);
|
||||
|
||||
return (image, texture, await FilamentApp.instance!.createTextureSampler());
|
||||
}
|
||||
|
||||
Future<(MaterialInstance, Texture)> _makeVDTMMaterial(
|
||||
ThermionViewer viewer,
|
||||
List<Vector3> cameraForwardVectors,
|
||||
int width,
|
||||
int height,
|
||||
int channels,
|
||||
) async {
|
||||
final sampler = await FilamentApp.instance!.createTextureSampler(
|
||||
compareMode: TextureCompareMode.COMPARE_TO_TEXTURE,
|
||||
compareFunc: TextureCompareFunc.GREATER);
|
||||
|
||||
var texture = await FilamentApp.instance!.createTexture(
|
||||
width,
|
||||
height,
|
||||
textureSamplerType: TextureSamplerType.SAMPLER_3D,
|
||||
depth: cameraForwardVectors.length,
|
||||
textureFormat: TextureFormat.RGBA32F,
|
||||
);
|
||||
|
||||
final vdtm = await FilamentApp.instance!.createMaterial(
|
||||
File(
|
||||
"/Users/nickfisher/Documents/thermion/materials/vdtm.filamat",
|
||||
).readAsBytesSync(),
|
||||
);
|
||||
|
||||
final materialInstance = await vdtm.createInstance();
|
||||
await materialInstance.setParameterBool("flipUVs", true);
|
||||
await materialInstance.setParameterFloat3Array(
|
||||
"cameraForwardVectors",
|
||||
cameraForwardVectors,
|
||||
);
|
||||
await materialInstance.setParameterTexture(
|
||||
"perspectives",
|
||||
texture,
|
||||
sampler,
|
||||
);
|
||||
return (materialInstance, texture);
|
||||
}
|
||||
|
||||
Future<ThermionAsset> _makeCube(
|
||||
TestHelper testHelper, ThermionViewer viewer) async {
|
||||
final cube = await testHelper.createCube(viewer);
|
||||
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.setParameterFloat4("baseColorFactor", 1.0, 1.0, 1.0, 0.0);
|
||||
|
||||
return cube;
|
||||
}
|
||||
|
||||
void main() async {
|
||||
final testHelper = TestHelper("vdtm");
|
||||
await testHelper.setup();
|
||||
test('basic color interpolation', () async {
|
||||
await testHelper.withViewer((viewer) async {
|
||||
final dist = 5.0;
|
||||
final numPositions = 3;
|
||||
final cameraPositions = List<Vector3>.generate(
|
||||
numPositions,
|
||||
(i) => Vector3(
|
||||
sin(i / numPositions * pi / 4) * dist,
|
||||
dist,
|
||||
cos(i / numPositions * pi / 4) * dist,
|
||||
),
|
||||
);
|
||||
|
||||
final cameraForwardVectors = cameraPositions.map((c) {
|
||||
var viewMatrix = makeViewMatrix(c, Vector3.zero(), Vector3(0, 1, 0));
|
||||
viewMatrix.invert();
|
||||
return -viewMatrix.forward;
|
||||
}).toList();
|
||||
|
||||
final camera = await viewer.view.getCamera();
|
||||
|
||||
final (numCameraPositions, width, height, channels) = (
|
||||
cameraPositions.length,
|
||||
1,
|
||||
1,
|
||||
4,
|
||||
);
|
||||
final (vdtmMi, texture) = await _makeVDTMMaterial(
|
||||
viewer, cameraForwardVectors, width, height, channels);
|
||||
|
||||
await FilamentApp.instance!.flush();
|
||||
final cube = await _makeCube(testHelper, viewer);
|
||||
await cube.setMaterialInstanceAt(vdtmMi);
|
||||
for (int i = 0; i < numCameraPositions; i++) {
|
||||
await camera.lookAt(cameraPositions[i]);
|
||||
final pixelBuffer = Float32List.fromList([
|
||||
1 - (i / numCameraPositions),
|
||||
i / numCameraPositions,
|
||||
0.0,
|
||||
1.0,
|
||||
]);
|
||||
var byteBuffer = pixelBuffer.buffer.asUint8List(
|
||||
pixelBuffer.offsetInBytes,
|
||||
);
|
||||
await texture.setImage3D(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
i,
|
||||
width,
|
||||
height,
|
||||
channels,
|
||||
1,
|
||||
byteBuffer,
|
||||
PixelDataFormat.RGBA,
|
||||
PixelDataType.FLOAT,
|
||||
);
|
||||
await testHelper.capture(viewer.view, "vdtm_interpolated_$i");
|
||||
}
|
||||
}, addSkybox: true);
|
||||
});
|
||||
|
||||
test('static texture check', () async {
|
||||
await testHelper.withViewer((viewer) async {
|
||||
final dist = 5.0;
|
||||
final numPositions = 3;
|
||||
final cameraPositions = List<Vector3>.generate(
|
||||
numPositions,
|
||||
(i) => Vector3(
|
||||
sin(i / (numPositions - 1) * pi / 2) * dist,
|
||||
0,
|
||||
cos(i / (numPositions - 1) * pi / 2) * dist,
|
||||
),
|
||||
);
|
||||
final cameraForwardVectors = cameraPositions.map((c) {
|
||||
var viewMatrix = makeViewMatrix(c, Vector3.zero(), Vector3(0, 1, 0));
|
||||
viewMatrix.invert();
|
||||
var forward = (-viewMatrix.forward).normalized();
|
||||
return forward;
|
||||
}).toList();
|
||||
|
||||
final camera = await viewer.view.getCamera();
|
||||
final vp = await viewer.view.getViewport();
|
||||
final (width, height) = (vp.width, vp.height);
|
||||
|
||||
final cube = await _makeCube(testHelper, viewer);
|
||||
final ubershader = await cube.getMaterialInstanceAt();
|
||||
|
||||
final (image, originalTexture, sampler) =
|
||||
await createTextureFromImage(testHelper);
|
||||
await ubershader.setParameterTexture(
|
||||
"baseColorMap", originalTexture, sampler);
|
||||
|
||||
await testHelper.capture(viewer.view, "vdtm_static_texture_initial");
|
||||
|
||||
final (vdtmMi, texture) = await _makeVDTMMaterial(
|
||||
viewer,
|
||||
cameraForwardVectors,
|
||||
await image.getWidth(),
|
||||
await image.getHeight(),
|
||||
await image.getChannels());
|
||||
|
||||
await cube.setMaterialInstanceAt(vdtmMi);
|
||||
|
||||
final pixelData = (await image.getData()).buffer.asUint8List();
|
||||
for (int i = 0; i < cameraPositions.length; i++) {
|
||||
await camera.lookAt(cameraPositions[i]);
|
||||
await texture.setImage3D(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
i,
|
||||
await image.getWidth(),
|
||||
await image.getHeight(),
|
||||
await image.getChannels(),
|
||||
1,
|
||||
pixelData,
|
||||
PixelDataFormat.RGBA,
|
||||
PixelDataType.FLOAT,
|
||||
);
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
await testHelper.capture(viewer.view, "vdtm_static_texture_$i");
|
||||
}
|
||||
}, addSkybox: true);
|
||||
});
|
||||
|
||||
test('VDTM + texture projection', () async {
|
||||
await testHelper.withViewer((viewer) async {
|
||||
final dist = 5.0;
|
||||
final numPositions = 3;
|
||||
final cameraPositions = List<Vector3>.generate(
|
||||
numPositions,
|
||||
(i) => Vector3(
|
||||
sin(i / numPositions * pi) * dist,
|
||||
dist,
|
||||
cos(i / numPositions * pi) * dist,
|
||||
),
|
||||
);
|
||||
final cameraForwardVectors = cameraPositions.map((c) {
|
||||
var viewMatrix = makeViewMatrix(c, Vector3.zero(), Vector3(0, 1, 0));
|
||||
viewMatrix.invert();
|
||||
return -viewMatrix.forward;
|
||||
}).toList();
|
||||
final camera = await viewer.view.getCamera();
|
||||
await camera.setLensProjection(near: 0.75, far: 100);
|
||||
final vp = await viewer.view.getViewport();
|
||||
|
||||
final (numCameraPositions, width, height, channels) = (
|
||||
cameraPositions.length,
|
||||
vp.width,
|
||||
vp.height,
|
||||
4,
|
||||
);
|
||||
|
||||
final (image, originalTexture, sampler) =
|
||||
await createTextureFromImage(testHelper);
|
||||
|
||||
final (vdtmMi, vdtmTexture) = await _makeVDTMMaterial(
|
||||
viewer, cameraForwardVectors, width, height, 4);
|
||||
|
||||
await FilamentApp.instance!.flush();
|
||||
|
||||
final cube = await _makeCube(testHelper, viewer);
|
||||
|
||||
final ubershader = await cube.getMaterialInstanceAt();
|
||||
|
||||
await ubershader.setParameterTexture(
|
||||
"baseColorMap", originalTexture, sampler);
|
||||
|
||||
final textureProjection =
|
||||
await TextureProjection.create(viewer.view, testHelper.swapChain);
|
||||
|
||||
await FilamentApp.instance!.setClearOptions(0, 0, 0, 1,
|
||||
clearStencil: 0, discard: false, clear: true);
|
||||
|
||||
final projectedImage =
|
||||
await FilamentApp.instance!.createImage(width, height, 4);
|
||||
final projectedTexture = await FilamentApp.instance!.createTexture(
|
||||
width,
|
||||
height,
|
||||
textureFormat: TextureFormat.RGBA32F,
|
||||
);
|
||||
|
||||
print(cameraForwardVectors[0].dot(cameraForwardVectors[1]));
|
||||
|
||||
// capture the cube with its original texture from each camera position
|
||||
for (final entry in cameraPositions.asMap().entries) {
|
||||
var (i, position) = (entry.key, entry.value);
|
||||
await camera.lookAt(position);
|
||||
|
||||
await textureProjection.project(cube);
|
||||
final projectedPixelBuffer =
|
||||
textureProjection.getProjectedPixelBuffer();
|
||||
await cube.setMaterialInstanceAt(ubershader);
|
||||
|
||||
await savePixelBufferToBmp(textureProjection.getColorBuffer(), width,
|
||||
height, "${testHelper.outDir.path}/initial_$i.bmp");
|
||||
// await savePixelBufferToBmp(projectedPixelBuffer, width, height,
|
||||
// "${testHelper.outDir.path}/initial_projected_uv_mapped_$i.bmp");
|
||||
|
||||
await vdtmTexture.setImage3D(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
i,
|
||||
width,
|
||||
height,
|
||||
4,
|
||||
1,
|
||||
projectedPixelBuffer.buffer.asUint8List(),
|
||||
PixelDataFormat.RGBA,
|
||||
PixelDataType.FLOAT);
|
||||
|
||||
final data = await projectedImage.getData();
|
||||
data.setRange(
|
||||
0, data.length, projectedPixelBuffer.buffer.asFloat32List());
|
||||
await projectedTexture.setLinearImage(
|
||||
projectedImage,
|
||||
PixelDataFormat.RGBA,
|
||||
PixelDataType.FLOAT,
|
||||
);
|
||||
await ubershader.setParameterTexture(
|
||||
"baseColorMap", projectedTexture, sampler);
|
||||
await cube.setMaterialInstanceAt(ubershader);
|
||||
// await testHelper.capture(viewer.view, "initial_reprojected_$i");
|
||||
|
||||
await cube.setMaterialInstanceAt(vdtmMi);
|
||||
|
||||
await testHelper.capture(viewer.view, "vdtm_$i");
|
||||
await cube.setMaterialInstanceAt(ubershader);
|
||||
await ubershader.setParameterTexture(
|
||||
"baseColorMap", originalTexture, sampler);
|
||||
}
|
||||
|
||||
await cube.setMaterialInstanceAt(vdtmMi);
|
||||
|
||||
// now check in between camera positions
|
||||
for (int i = 0; i < 6; i++) {
|
||||
final cameraPosition = Vector3(
|
||||
sin(i / 6 * pi / 4) * dist,
|
||||
dist,
|
||||
cos(i / 6 * pi / 4) * dist,
|
||||
);
|
||||
await camera.lookAt(cameraPosition);
|
||||
await testHelper.capture(viewer.view, "vdtm_interpolated_texture_$i");
|
||||
}
|
||||
}, createRenderTarget: true);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user