| @@ -18,7 +18,32 @@ async function init() { | |||
| }) | |||
| createSimpleButtons({ | |||
| ['Download snapshot (rect png)']: async(btn: HTMLButtonElement) => { | |||
| ['Download snapshot (jpeg)']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| await snapshotPlugin.downloadSnapshot('snapshot.jpeg', { | |||
| mimeType: 'image/jpeg', // mime type of the image | |||
| quality: 0.9, // quality of the image (0-1) only for jpeg and webp | |||
| displayPixelRatio: 2, // render scale | |||
| }) | |||
| btn.disabled = false | |||
| }, | |||
| ['Download snapshot (1024x1024 size, png)']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| // save scale | |||
| const scale = viewer.renderManager.renderScale | |||
| // set fixed render size | |||
| viewer.setRenderSize({width: 1024, height: 1024}) | |||
| // (optional) hide the canvas. (not needed if you have an overlay) | |||
| await snapshotPlugin.downloadSnapshot('snapshot.png', { | |||
| mimeType: 'image/png', // mime type of the image | |||
| }) | |||
| // revert scale | |||
| viewer.renderManager.renderScale = scale | |||
| // revert render size to fill container | |||
| viewer.setSize() | |||
| btn.disabled = false | |||
| }, | |||
| ['Download snapshot (crop rect, png)']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| await snapshotPlugin.downloadSnapshot('snapshot.png', { | |||
| scale: 1, // scale the final image | |||
| @@ -33,15 +58,6 @@ async function init() { | |||
| }) | |||
| btn.disabled = false | |||
| }, | |||
| ['Download snapshot (jpeg)']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| await snapshotPlugin.downloadSnapshot('snapshot.jpeg', { | |||
| mimeType: 'image/jpeg', // mime type of the image | |||
| quality: 0.9, // quality of the image (0-1) only for jpeg and webp | |||
| displayPixelRatio: 2, // render scale | |||
| }) | |||
| btn.disabled = false | |||
| }, | |||
| ['Download snapshot (webp)']: async(btn: HTMLButtonElement) => { | |||
| btn.disabled = true | |||
| if (!isWebpExportSupported()) { | |||
| @@ -364,6 +364,7 @@ | |||
| <li><a href="./custom-pipeline/">Custom Pipeline specification </a></li> | |||
| <li><a href="./ssaa-plugin/">SSAA Plugin </a></li> | |||
| <li><a href="./msaa-ssaa/">MSAA + SSAA </a></li> | |||
| <li><a href="./viewer-render-size/">Viewer Render Size </a></li> | |||
| <li><a href="./depth-buffer-plugin/">Depth Buffer Plugin </a></li> | |||
| <li><a href="./normal-buffer-plugin/">Normal Buffer Plugin </a></li> | |||
| <li><a href="./gbuffer-plugin/">GBuffer Plugin <br/>(NormalDepth+Flags) </a></li> | |||
| @@ -531,6 +532,7 @@ | |||
| <li><a href="./sphere-msaa-test/">MSAA Test </a></li> | |||
| <li><a href="./z-prepass/">Z-Prepass Test </a></li> | |||
| <li><a href="./import-test/">Import Test</a></li> | |||
| <li><a href="./js-image-data-test/">JS ImageData Test</a></li> | |||
| <li><a href="./gltf-transmission-test-msaa-zprepass/">glTF Transmission Test + MSAA + zPrepass</a></li> | |||
| </ul> | |||
| </div> | |||
| @@ -0,0 +1,52 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>JS ImageData test</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module"> | |||
| import {_testFinish, Mesh, SphereGeometry, ThreeViewer, UnlitMaterial, Texture} from 'threepipe' | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas'), | |||
| rgbm: true, | |||
| }) | |||
| const sphere = new Mesh(new SphereGeometry(1, 32, 32), new UnlitMaterial({color: '#ffffff'})) | |||
| const data = new ImageData(new Uint8ClampedArray([0, 255, 255, 255]), 1, 1) | |||
| sphere.material.map = new Texture(data) | |||
| // sphere.material.map.needsUpdate = true // not required since three.js v0.157.1006 | |||
| viewer.scene.addObject(sphere) | |||
| _testFinish() | |||
| </script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,36 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8"> | |||
| <title>Viewer Render Size</title> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <!-- Import maps polyfill --> | |||
| <!-- Remove this when import maps will be widely supported --> | |||
| <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script> | |||
| <script type="importmap"> | |||
| { | |||
| "imports": { | |||
| "threepipe": "./../../dist/index.mjs", | |||
| "@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs" | |||
| } | |||
| } | |||
| </script> | |||
| <style id="example-style"> | |||
| html, body, #canvas-container, #mcanvas { | |||
| width: 100%; | |||
| height: 100%; | |||
| margin: 0; | |||
| overflow: hidden; | |||
| } | |||
| </style> | |||
| <script type="module" src="../examples-utils/simple-code-preview.mjs"></script> | |||
| <script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script> | |||
| </head> | |||
| <body> | |||
| <div id="canvas-container"> | |||
| <canvas id="mcanvas"></canvas> | |||
| </div> | |||
| </body> | |||
| @@ -0,0 +1,89 @@ | |||
| import {_testFinish, IObject3D, LoadingScreenPlugin, ThreeViewer} from 'threepipe' | |||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||
| async function init() { | |||
| const viewer = new ThreeViewer({ | |||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||
| msaa: true, | |||
| plugins: [LoadingScreenPlugin], | |||
| }) | |||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true)) | |||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', { | |||
| setBackground: true, | |||
| }) | |||
| await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', { | |||
| autoCenter: true, | |||
| autoScale: true, | |||
| }) | |||
| // setup css alignment of canvas inside container | |||
| viewer.container.style.position = 'relative' | |||
| viewer.canvas.style.position = 'absolute' | |||
| viewer.canvas.style.top = '50%' | |||
| viewer.canvas.style.left = '50%' | |||
| viewer.canvas.style.transform = 'translate(-50%, -50%)' | |||
| const state = { | |||
| width: 1280, | |||
| height: 768, | |||
| mode: 'contain' as 'contain' | 'cover' | 'fill' | 'scale-down' | 'none', | |||
| dpr: 1, | |||
| alignX: 0, | |||
| alignY: 0, | |||
| } | |||
| viewer.setRenderSize({width: state.width, height: state.height}, state.mode, state.dpr) | |||
| ui.appendChild({ | |||
| type: 'folder', | |||
| label: 'Render Size', | |||
| value: state, | |||
| expanded: true, | |||
| onChange: ()=>{ | |||
| viewer.setRenderSize({width: state.width, height: state.height}, state.mode, state.dpr) | |||
| viewer.canvas.style.transform = `translate(${state.alignX * 100 - 50}%, ${state.alignY * 100 - 50}%)` | |||
| }, | |||
| children: [{ | |||
| type: 'slider', | |||
| label: 'Width', | |||
| path: 'width', | |||
| bounds: [10, 2048], | |||
| stepSize: 10, | |||
| }, { | |||
| type: 'slider', | |||
| label: 'Height', | |||
| path: 'height', | |||
| bounds: [10, 2048], | |||
| stepSize: 10, | |||
| }, { | |||
| type: 'dropdown', | |||
| label: 'Mode', | |||
| children: ['contain', 'cover', 'fill', 'scale-down', 'none'].map((v) => ({label: v})), | |||
| path: 'mode', | |||
| }, { | |||
| type: 'slider', | |||
| label: 'DPR', | |||
| path: 'dpr', | |||
| bounds: [0.1, 4], | |||
| stepSize: 0.1, | |||
| }, { | |||
| type: 'slider', | |||
| label: 'AlignX', | |||
| path: 'alignX', | |||
| bounds: [-1, 1], | |||
| stepSize: 0.01, | |||
| }, { | |||
| type: 'slider', | |||
| label: 'AlignY', | |||
| path: 'alignY', | |||
| bounds: [-1, 1], | |||
| stepSize: 0.01, | |||
| }], | |||
| }) | |||
| } | |||
| init().finally(_testFinish) | |||