| @@ -0,0 +1,36 @@ | |||
| <!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> | |||
| @@ -0,0 +1,53 @@ | |||
| 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) | |||
| @@ -527,6 +527,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="./gltf-transmission-test-msaa-zprepass/">glTF Transmission Test + MSAA + zPrepass</a></li> | |||
| </ul> | |||
| </div> | |||
| <div class="iframe-container"> | |||
| @@ -33,6 +33,7 @@ const hdris = [ | |||
| '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_01_1k.hdr', | |||
| 'https://hdrihaven.r2cache.com/hdr/1k/empty_warehouse_01_1k.hdr', | |||
| ] | |||
| async function init() { | |||
| @@ -15,7 +15,7 @@ | |||
| "popmotion": "^11.0.5", | |||
| "stats.js": "^0.17.0", | |||
| "ts-browser-helpers": "^0.16.2", | |||
| "uiconfig.js": "^0.1.2" | |||
| "uiconfig.js": "^0.1.3" | |||
| }, | |||
| "devDependencies": { | |||
| "@rollup/plugin-json": "^6.0.0", | |||
| @@ -10310,9 +10310,9 @@ | |||
| "license": "MIT" | |||
| }, | |||
| "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" | |||
| }, | |||
| "node_modules/unbox-primitive": { | |||
| @@ -1,6 +1,6 @@ | |||
| { | |||
| "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.", | |||
| "main": "dist/index.js", | |||
| "module": "dist/index.mjs", | |||
| @@ -124,7 +124,7 @@ | |||
| "@types/wicg-file-system-access": "^2020.9.5", | |||
| "stats.js": "^0.17.0", | |||
| "ts-browser-helpers": "^0.16.2", | |||
| "uiconfig.js": "^0.1.2", | |||
| "uiconfig.js": "^0.1.3", | |||
| "popmotion": "^11.0.5" | |||
| }, | |||
| "peerDependencies": { | |||
| @@ -137,7 +137,7 @@ | |||
| }, | |||
| "//": { | |||
| "dependencies": { | |||
| "uiconfig.js": "^0.1.2", | |||
| "uiconfig.js": "^0.1.3", | |||
| "ts-browser-helpers": "^0.16.2", | |||
| "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", | |||
| @@ -51,8 +51,10 @@ export abstract class PipelinePassPlugin<T extends IPipelinePass, TPassId extend | |||
| } | |||
| 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 | |||
| super.onRemove(viewer) | |||
| } | |||
| @@ -47,7 +47,7 @@ export class ContactShadowGroundPlugin extends BaseGroundPlugin { | |||
| 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 | |||
| constructor() { | |||
| @@ -26,6 +26,7 @@ export class ExtendedShaderPass extends ShaderPass implements IPass { | |||
| this.setDirty = this.setDirty.bind(this) | |||
| } | |||
| // writes to writeBuffer | |||
| render(renderer: IWebGLRenderer, writeBuffer?: WebGLMultipleRenderTargets|WebGLRenderTarget|null, readBuffer?: WebGLMultipleRenderTargets|WebGLRenderTarget, deltaTime?: number, maskActive?: boolean) { | |||
| if (!this.enabled) return | |||
| renderer.renderWithModes({ | |||
| @@ -6,7 +6,7 @@ import {uiFolderContainer, UiObjectConfig, uiToggle} from 'uiconfig.js' | |||
| import {getOrCall, ValOrFunc} from 'ts-browser-helpers' | |||
| @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 | |||
| uiConfig: UiObjectConfig | |||
| @@ -691,6 +691,11 @@ export class RenderManager<TEvent extends BaseEvent = IRenderManagerEvent, TEven | |||
| if (unregister === true) disposeTarget(this, true) | |||
| else super.dispose() | |||
| } | |||
| // required for uiconfig.js. see UiConfigMethods.getValue | |||
| // eslint-disable-next-line @typescript-eslint/naming-convention | |||
| _ui_isPrimitive = true | |||
| }(this, ...size, options) | |||
| } | |||
| @@ -230,6 +230,9 @@ export {Pass, FullScreenQuad} from 'three/examples/jsm/postprocessing/Pass.js' | |||
| export {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass.js' | |||
| export {ShaderPass} from 'three/examples/jsm/postprocessing/ShaderPass.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 * from 'three/examples/jsm/utils/BufferGeometryUtils.js' | |||
| @@ -18,13 +18,14 @@ import { | |||
| } from 'three' | |||
| 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' | |||
| return { | |||
| 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: [ | |||
| ()=>({ | |||
| type: 'vec2', | |||
| @@ -111,13 +112,12 @@ export function makeSamplerUi<T extends IMaterial>(mat: T, map: keyof T) { | |||
| t1.source.data = imageBitmap | |||
| t1.source.needsUpdate = true | |||
| t1.needsUpdate = true | |||
| mat?.setDirty?.() | |||
| setDirty() | |||
| }) | |||
| } else { | |||
| tex.flipY = value | |||
| tex.needsUpdate = true | |||
| mat?.setDirty?.() | |||
| setDirty() | |||
| } | |||
| }, | |||