threepipe
Version:
A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.
76 lines (75 loc) • 3.61 kB
JavaScript
import { _testFinish, downloadBlob, FloatType, GBufferPlugin, HalfFloatType, LoadingScreenPlugin, RenderTargetPreviewPlugin, ThreeViewer, } from 'threepipe';
import { createSimpleButtons } from '../examples-utils/simple-bottom-buttons.js';
const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas'),
msaa: true,
zPrepass: true,
plugins: [LoadingScreenPlugin],
});
async function init() {
const gbufferPlugin = viewer.addPluginSync(new GBufferPlugin(HalfFloatType, true, // isPrimaryGBuffer (used for zprepass etc)
true, // enabled by default
true, // render the flags buffer (used for eg selective tonemapping)
true, // render depth texture
FloatType)); // render depth texture as Float type. available - UnsignedShort(16 bits), UnsignedInt(24 bits) or Float(32 bits)
await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr');
const model = await viewer.load('https://threejs.org/examples/models/gltf/kira.glb', {
autoCenter: true,
autoScale: true,
});
let id = 1;
model?.traverse((o) => {
o.materials?.forEach(m => {
if (!m.userData.gBufferData)
m.userData.gBufferData = {};
if (!m.userData.gBufferData.materialId)
m.userData.gBufferData.materialId = id += 10;
});
});
// Disable automatic near/far plane calculation based on scene bounding box
viewer.scene.mainCamera.userData.autoNearFar = false;
viewer.scene.mainCamera.userData.minNearPlane = 1;
viewer.scene.mainCamera.userData.maxFarPlane = 10;
viewer.scene.refreshScene();
const gbufferTarget = gbufferPlugin.target;
if (!gbufferTarget) {
throw new Error('gbufferPlugin.target returned undefined');
}
// to render depth buffer to screen, uncomment this line:
// viewer.renderManager.screenPass.overrideReadBuffer = gbufferTarget
const getNormalDepth = () => ({ texture: gbufferPlugin.normalDepthTexture });
const getFlags = () => ({ texture: gbufferPlugin.flagsTexture });
const getDepthTexture = () => ({ texture: gbufferPlugin.depthTexture });
const targetPreview = await viewer.addPlugin(RenderTargetPreviewPlugin);
targetPreview.addTarget(getNormalDepth, 'normalDepth');
targetPreview.addTarget(getFlags, 'gBufferFlags');
targetPreview.addTarget(getDepthTexture, 'depthTexture');
const screenPass = viewer.renderManager.screenPass;
createSimpleButtons({
['Toggle Normal+Depth']: () => {
const rt = getNormalDepth();
screenPass.overrideReadBuffer = screenPass.overrideReadBuffer?.texture === rt.texture ? null : rt;
viewer.setDirty();
},
['Toggle Gbuffer Flags']: () => {
const rt = getFlags();
screenPass.overrideReadBuffer = screenPass.overrideReadBuffer?.texture === rt.texture ? null : rt;
viewer.setDirty();
},
['Toggle Depth Texture']: () => {
const rt = getDepthTexture();
screenPass.overrideReadBuffer = screenPass.overrideReadBuffer?.texture === rt.texture ? null : rt;
viewer.setDirty();
},
['Download snapshot']: async (btn) => {
btn.disabled = true;
const blob = await viewer.getScreenshotBlob({ mimeType: 'image/png' });
if (blob)
downloadBlob(blob, 'file.png');
else
console.error('Unable to get screenshot');
btn.disabled = false;
},
});
}
init().finally(_testFinish);