| <!DOCTYPE html> | |||||
| <html lang="en"> | |||||
| <head> | |||||
| <meta charset="UTF-8"> | |||||
| <title>GLTF Transmission Test (MSAA)</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> |
| import {_testFinish, IObject3D, LoadingScreenPlugin, RenderTargetPreviewPlugin, ThreeViewer} from 'threepipe' | |||||
| import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane' | |||||
| const viewer = new ThreeViewer({ | |||||
| canvas: document.getElementById('mcanvas') as HTMLCanvasElement, | |||||
| msaa: true, | |||||
| rgbm: true, | |||||
| zPrepass: true, // This example shows a bug in zPrepass | |||||
| plugins: [LoadingScreenPlugin], | |||||
| }) | |||||
| async function init() { | |||||
| const targetPreview = viewer.addPluginSync(RenderTargetPreviewPlugin) | |||||
| targetPreview.addTarget(()=>viewer.renderManager.composerTarget, 'composer-1', false, false) | |||||
| viewer.renderManager.renderPass.preserveTransparentTarget = true | |||||
| targetPreview.addTarget(()=>viewer.renderManager.renderPass.transparentTarget, 'transparent', true, true) | |||||
| targetPreview.addTarget(()=>viewer.renderManager.composerTarget2, 'composer-2', false, false) | |||||
| await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr') | |||||
| const [model, model2] = await Promise.all([ | |||||
| viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/IridescenceLamp.glb', { | |||||
| autoCenter: true, | |||||
| autoScale: true, | |||||
| }), | |||||
| viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/IridescentDishWithOlives.glb', { | |||||
| autoCenter: true, | |||||
| autoScale: true, | |||||
| }), | |||||
| ]) | |||||
| if (!model || !model2) { | |||||
| console.error('model not loaded') | |||||
| return | |||||
| } | |||||
| model.position.x = -1 | |||||
| model2.position.x = 1 | |||||
| model2.position.y = -1.2 | |||||
| const ui = viewer.addPluginSync(new TweakpaneUiPlugin(false)) | |||||
| const m1 = model?.getObjectByName('lamp_transmission') | |||||
| const m2 = model2?.getObjectByName('glassCover') | |||||
| const materials = [...m1?.materials || [], ...m2?.materials || []] | |||||
| for (const material of materials) { | |||||
| const config = material.uiConfig | |||||
| if (!config) continue | |||||
| ui.appendChild(config) | |||||
| } | |||||
| } | |||||
| init().finally(_testFinish) |
| <li><a href="./sphere-msaa-test/">MSAA Test </a></li> | <li><a href="./sphere-msaa-test/">MSAA Test </a></li> | ||||
| <li><a href="./z-prepass/">Z-Prepass 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="./import-test/">Import Test</a></li> | ||||
| <li><a href="./gltf-transmission-test-msaa-zprepass/">glTF Transmission Test + MSAA + zPrepass</a></li> | |||||
| </ul> | </ul> | ||||
| </div> | </div> | ||||
| <div class="iframe-container"> | <div class="iframe-container"> |
| 'https://hdrihaven.r2cache.com/hdr/1k/studio_small_05_1k.hdr', | 'https://hdrihaven.r2cache.com/hdr/1k/studio_small_05_1k.hdr', | ||||
| 'https://hdrihaven.r2cache.com/hdr/1k/studio_small_02_1k.hdr', | 'https://hdrihaven.r2cache.com/hdr/1k/studio_small_02_1k.hdr', | ||||
| 'https://hdrihaven.r2cache.com/hdr/1k/studio_small_01_1k.hdr', | 'https://hdrihaven.r2cache.com/hdr/1k/studio_small_01_1k.hdr', | ||||
| 'https://hdrihaven.r2cache.com/hdr/1k/empty_warehouse_01_1k.hdr', | |||||
| ] | ] | ||||
| async function init() { | async function init() { |
| "popmotion": "^11.0.5", | "popmotion": "^11.0.5", | ||||
| "stats.js": "^0.17.0", | "stats.js": "^0.17.0", | ||||
| "ts-browser-helpers": "^0.16.2", | "ts-browser-helpers": "^0.16.2", | ||||
| "uiconfig.js": "^0.1.2" | |||||
| "uiconfig.js": "^0.1.3" | |||||
| }, | }, | ||||
| "devDependencies": { | "devDependencies": { | ||||
| "@rollup/plugin-json": "^6.0.0", | "@rollup/plugin-json": "^6.0.0", | ||||
| "license": "MIT" | "license": "MIT" | ||||
| }, | }, | ||||
| "node_modules/uiconfig.js": { | "node_modules/uiconfig.js": { | ||||
| "version": "0.1.2", | |||||
| "resolved": "https://registry.npmjs.org/uiconfig.js/-/uiconfig.js-0.1.2.tgz", | |||||
| "integrity": "sha512-J6Rgu6L3YB4guzcYmGspMlNTRBXlvdwFRG0nMMY+VlQJFuiE1i76UsAm+sssbZN6OTlPZzqonrSZFlLtCGkM7w==", | |||||
| "version": "0.1.3", | |||||
| "resolved": "https://registry.npmjs.org/uiconfig.js/-/uiconfig.js-0.1.3.tgz", | |||||
| "integrity": "sha512-Q3eXWGrwXO46lkjfCsMQX6fsMKLmg4u4rrvZMkRJlQiDmsQyCaDdIJy7CMKrBWWfL9e6f4w+66SHAb+u4rOL2g==", | |||||
| "license": "MIT" | "license": "MIT" | ||||
| }, | }, | ||||
| "node_modules/unbox-primitive": { | "node_modules/unbox-primitive": { |
| { | { | ||||
| "name": "threepipe", | "name": "threepipe", | ||||
| "version": "0.0.35", | |||||
| "version": "0.0.35-dev", | |||||
| "description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.", | "description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.", | ||||
| "main": "dist/index.js", | "main": "dist/index.js", | ||||
| "module": "dist/index.mjs", | "module": "dist/index.mjs", | ||||
| "@types/wicg-file-system-access": "^2020.9.5", | "@types/wicg-file-system-access": "^2020.9.5", | ||||
| "stats.js": "^0.17.0", | "stats.js": "^0.17.0", | ||||
| "ts-browser-helpers": "^0.16.2", | "ts-browser-helpers": "^0.16.2", | ||||
| "uiconfig.js": "^0.1.2", | |||||
| "uiconfig.js": "^0.1.3", | |||||
| "popmotion": "^11.0.5" | "popmotion": "^11.0.5" | ||||
| }, | }, | ||||
| "peerDependencies": { | "peerDependencies": { | ||||
| }, | }, | ||||
| "//": { | "//": { | ||||
| "dependencies": { | "dependencies": { | ||||
| "uiconfig.js": "^0.1.2", | |||||
| "uiconfig.js": "^0.1.3", | |||||
| "ts-browser-helpers": "^0.16.2", | "ts-browser-helpers": "^0.16.2", | ||||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.153.1006/package.tgz", | "three": "https://github.com/repalash/three.js-modded/releases/download/v0.153.1006/package.tgz", | ||||
| "three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.153.1006.tar.gz", | "three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.153.1006.tar.gz", |
| } | } | ||||
| onRemove(viewer: TViewer): void { | onRemove(viewer: TViewer): void { | ||||
| if (this._pass) viewer.renderManager.unregisterPass(this._pass) | |||||
| this._pass?.dispose?.() | |||||
| if (this._pass) { | |||||
| viewer.renderManager.unregisterPass(this._pass) | |||||
| if (this._pass.dispose) this._pass.dispose() | |||||
| } | |||||
| this._pass = undefined | this._pass = undefined | ||||
| super.onRemove(viewer) | super.onRemove(viewer) | ||||
| } | } |
| shadowCamera = new OrthographicCamera(-1, 1, 1, -1, 0.001, this.shadowHeight) | shadowCamera = new OrthographicCamera(-1, 1, 1, -1, 0.001, this.shadowHeight) | ||||
| private _depthPass?: GBufferRenderPass<'contactShadowGround', WebGLRenderTarget> | |||||
| private _depthPass?: GBufferRenderPass<'contactShadowGround', WebGLRenderTarget|undefined> | |||||
| private _blurHelper?: HVBlurHelper | private _blurHelper?: HVBlurHelper | ||||
| constructor() { | constructor() { |
| this.setDirty = this.setDirty.bind(this) | this.setDirty = this.setDirty.bind(this) | ||||
| } | } | ||||
| // writes to writeBuffer | |||||
| render(renderer: IWebGLRenderer, writeBuffer?: WebGLMultipleRenderTargets|WebGLRenderTarget|null, readBuffer?: WebGLMultipleRenderTargets|WebGLRenderTarget, deltaTime?: number, maskActive?: boolean) { | render(renderer: IWebGLRenderer, writeBuffer?: WebGLMultipleRenderTargets|WebGLRenderTarget|null, readBuffer?: WebGLMultipleRenderTargets|WebGLRenderTarget, deltaTime?: number, maskActive?: boolean) { | ||||
| if (!this.enabled) return | if (!this.enabled) return | ||||
| renderer.renderWithModes({ | renderer.renderWithModes({ |
| import {getOrCall, ValOrFunc} from 'ts-browser-helpers' | import {getOrCall, ValOrFunc} from 'ts-browser-helpers' | ||||
| @uiFolderContainer<GBufferRenderPass>((c)=>c.passId + ' Render Pass') | @uiFolderContainer<GBufferRenderPass>((c)=>c.passId + ' Render Pass') | ||||
| export class GBufferRenderPass<TP extends IPassID=IPassID, T extends WebGLMultipleRenderTargets | WebGLRenderTarget=WebGLMultipleRenderTargets | WebGLRenderTarget> extends RenderPass implements IPipelinePass<TP> { // todo: extend from jittered? | |||||
| export class GBufferRenderPass<TP extends IPassID=IPassID, T extends WebGLMultipleRenderTargets | WebGLRenderTarget|undefined=WebGLMultipleRenderTargets | WebGLRenderTarget> extends RenderPass implements IPipelinePass<TP> { // todo: extend from jittered? | |||||
| readonly isGBufferRenderPass = true | readonly isGBufferRenderPass = true | ||||
| uiConfig: UiObjectConfig | uiConfig: UiObjectConfig | ||||
| if (unregister === true) disposeTarget(this, true) | if (unregister === true) disposeTarget(this, true) | ||||
| else super.dispose() | else super.dispose() | ||||
| } | } | ||||
| // required for uiconfig.js. see UiConfigMethods.getValue | |||||
| // eslint-disable-next-line @typescript-eslint/naming-convention | |||||
| _ui_isPrimitive = true | |||||
| }(this, ...size, options) | }(this, ...size, options) | ||||
| } | } | ||||
| export {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass.js' | export {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass.js' | ||||
| export {ShaderPass} from 'three/examples/jsm/postprocessing/ShaderPass.js' | export {ShaderPass} from 'three/examples/jsm/postprocessing/ShaderPass.js' | ||||
| export {EffectComposer} from 'three/examples/jsm/postprocessing/EffectComposer.js' | export {EffectComposer} from 'three/examples/jsm/postprocessing/EffectComposer.js' | ||||
| export type {GLTFLoaderPlugin, GLTF, GLTFReference, GLTFReferenceType} from 'three/examples/jsm/loaders/GLTFLoader' | |||||
| export {GLTFParser, GLTFBinaryExtension, GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader' | |||||
| export {GLTFExporter} from 'three/examples/jsm/exporters/GLTFExporter' | |||||
| export {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' | export {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js' | ||||
| export * from 'three/examples/jsm/utils/BufferGeometryUtils.js' | export * from 'three/examples/jsm/utils/BufferGeometryUtils.js' |
| } from 'three' | } from 'three' | ||||
| import {UiObjectConfig} from 'uiconfig.js' | import {UiObjectConfig} from 'uiconfig.js' | ||||
| export function makeSamplerUi<T extends IMaterial>(mat: T, map: keyof T) { | |||||
| export function makeSamplerUi<T extends IMaterial>(mat: T, map: keyof T, label?: string, hidden?: ()=>boolean, setDirty?: ()=>any) { | |||||
| setDirty = setDirty ?? (()=>mat.setDirty && mat.setDirty()) | |||||
| // const im = map === 'map' | // const im = map === 'map' | ||||
| return { | return { | ||||
| type: 'folder', | type: 'folder', | ||||
| label: <string>map + ' Sampler', | |||||
| hidden: ()=>!mat[map], | |||||
| onChange: ()=>mat.setDirty(), | |||||
| label: label ?? <string>map + ' Sampler', | |||||
| hidden: ()=>!mat[map] || hidden && hidden(), | |||||
| onChange: setDirty, | |||||
| children: [ | children: [ | ||||
| ()=>({ | ()=>({ | ||||
| type: 'vec2', | type: 'vec2', | ||||
| t1.source.data = imageBitmap | t1.source.data = imageBitmap | ||||
| t1.source.needsUpdate = true | t1.source.needsUpdate = true | ||||
| t1.needsUpdate = true | t1.needsUpdate = true | ||||
| mat?.setDirty?.() | |||||
| setDirty() | |||||
| }) | }) | ||||
| } else { | } else { | ||||
| tex.flipY = value | tex.flipY = value | ||||
| tex.needsUpdate = true | tex.needsUpdate = true | ||||
| mat?.setDirty?.() | |||||
| setDirty() | |||||
| } | } | ||||
| }, | }, |