329 lines
10 KiB
Dart
329 lines
10 KiB
Dart
@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/bindings/bindings.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_texture_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);
|
|
});
|
|
}
|