Bladeren bron

ImagePass custom viewport

David Sehnal 4 jaren geleden
bovenliggende
commit
1de159d65c
2 gewijzigde bestanden met toevoegingen van 27 en 22 verwijderingen
  1. 19 17
      src/extensions/mp4-export/encoder.ts
  2. 8 5
      src/mol-canvas3d/passes/image.ts

+ 19 - 17
src/extensions/mp4-export/encoder.ts

@@ -1,4 +1,5 @@
 import * as HME from 'h264-mp4-encoder';
+import { Viewport } from '../../mol-canvas3d/camera/util';
 import { AnimateCameraSpin } from '../../mol-plugin-state/animation/built-in/camera-spin';
 import { PluginContext } from '../../mol-plugin/context';
 
@@ -6,7 +7,7 @@ export class Mp4Encoder {
 
     createImagePass() {
         const pass = this.plugin.canvas3d!.getImagePass({
-            transparentBackground: false,
+            transparentBackground: true,
             cameraHelper: { axes: { name: 'off', params: {} } },
             multiSample: { mode: 'on', sampleLevel: 4 }, // { mode: 'on', sampleLevel: 2 },
             postprocessing: this.plugin.canvas3d!.props.postprocessing
@@ -23,9 +24,16 @@ export class Mp4Encoder {
         // const w = 1920, h = 1080;
         const w = 1280, h = 720;
 
+        const viewport: Viewport = {
+            x: w / 2 - 300,
+            y: h / 2 - 250,
+            width: 600,
+            height: 500
+        };
+
         const encoder = await HME.createH264MP4Encoder();
-        encoder.width = w;
-        encoder.height = h;
+        encoder.width = viewport.width;
+        encoder.height = viewport.height;
         encoder.frameRate = 30;
         encoder.quantizationParameter = 15;
         encoder.initialize();
@@ -43,35 +51,29 @@ export class Mp4Encoder {
         loop.stop();
         loop.resetTime(0);
 
-        const durationMs = 5000;
+        const durationMs = 2500;
         const fps = encoder.frameRate;
 
+        const color = this.plugin.canvas3d?.props.renderer.backgroundColor;
+        this.plugin.canvas3d?.setProps({ renderer: { backgroundColor: 0x000000 as any } }, true);
+
         // await this.plugin.managers.animation.play(AnimateAssemblyUnwind, { durationInMs: 3000, playOnce: true, target: 'all' });
         await this.plugin.managers.animation.play(AnimateCameraSpin, { durationInMs: durationMs, direction: 'cw' });
 
         // const imageData: Uint8ClampedArray[] = [];
         const N = Math.ceil(durationMs / 1000 * fps);
-        const dt = durationMs / (N);
-        console.log({ w, h });
+        const dt = durationMs / N;
         for (let i = 0; i <= N; i++) {
+            await loop.tick(i * dt, { isSynchronous: true, manualDraw: true });
 
-            const t = i * dt;
-            await loop.tick(t, { isSynchronous: true, manualDraw: true });
-
-            const image = pass.getImageData(w, h);
+            const image = pass.getImageData(w, h, viewport);
             encoder.addFrameRgba(image.data);
             // if (i === 0) canvasCtx.putImageData(image, 0, 0);
 
-            // imageData.push(image.data);
             console.log(`frame ${i + 1}/${N + 1}`);
-            // await this.sleep();
         }
 
-        // let ii = 0;
-        // for (const f of imageData) {
-        //     encoder.addFrameRgba(f);
-        //     console.log(`added ${++ii}/${N}`);
-        // }
+        this.plugin.canvas3d?.setProps({ renderer: { backgroundColor: color } }, true);
 
         console.log('finalizing');
         encoder.finalize();

+ 8 - 5
src/mol-canvas3d/passes/image.ts

@@ -100,13 +100,16 @@ export class ImagePass {
         }
     }
 
-    getImageData(width: number, height: number) {
+    getImageData(width: number, height: number, viewport?: Viewport) {
         this.setSize(width, height);
         this.render();
         this.colorTarget.bind();
-        const array = new Uint8Array(width * height * 4);
-        this.webgl.readPixels(0, 0, width, height, array);
-        PixelData.flipY({ array, width, height });
-        return new ImageData(new Uint8ClampedArray(array), width, height);
+
+        const w = viewport?.width ?? width, h = viewport?.height ?? height;
+
+        const array = new Uint8Array(w * h * 4);
+        this.webgl.readPixels(viewport?.x ?? 0, viewport?.y ?? 0, w, h, array);
+        PixelData.flipY({ array, width: w, height: h });
+        return new ImageData(new Uint8ClampedArray(array), w, h);
     }
 }