Bläddra i källkod

Support stencil and add examples.

master
Palash Bansal 11 månader sedan
förälder
incheckning
29a191dc48
Inget konto är kopplat till bidragsgivarens mejladress

+ 6
- 7
examples/index.html Visa fil

<li><a href="./depthoffield-plugin/">DepthOfField Plugin </a></li> <li><a href="./depthoffield-plugin/">DepthOfField Plugin </a></li>
<li><a href="./ssreflection-plugin/">Screen Space Reflection(SSR) Plugin </a></li> <li><a href="./ssreflection-plugin/">Screen Space Reflection(SSR) Plugin </a></li>
<li><a href="./temporalaa-plugin/">Temporal Anti-aliasing(TAA) Plugin </a></li> <li><a href="./temporalaa-plugin/">Temporal Anti-aliasing(TAA) Plugin </a></li>
<li><a href="./outline-plugin/">Outline(Picking) Plugin </a></li>
<li><a href="./outline-plugin/">Outline (Picking) Plugin </a></li>
<li><a href="./ssgi-plugin/">Screen Space Global Illumination(SSGI) Plugin </a></li> <li><a href="./ssgi-plugin/">Screen Space Global Illumination(SSGI) Plugin </a></li>
<li><a href="./ssgi-ssr-plugin/">SSGI + SSR Plugins </a></li> <li><a href="./ssgi-ssr-plugin/">SSGI + SSR Plugins </a></li>
<!--<li><a href="./ssrtao-plugin/">Screen Space Ray Traced AO Plugin </a></li>--> <!--<li><a href="./ssrtao-plugin/">Screen Space Ray Traced AO Plugin </a></li>-->
<li><a href="./custom-bump-map-plugin/">Custom Bump Map Plugin </a></li> <li><a href="./custom-bump-map-plugin/">Custom Bump Map Plugin </a></li>
<li><a href="./parallax-mapping-plugin/">Parallax(Relief) Mapping Plugin </a></li> <li><a href="./parallax-mapping-plugin/">Parallax(Relief) Mapping Plugin </a></li>
</ul> </ul>
<h2 class="category">Utils</h2>
<h2 class="category">Utils / Experiments</h2>
<ul> <ul>
<li><a href="./contact-shadow-ground-plugin/">Contact Shadow Ground Plugin</a></li> <li><a href="./contact-shadow-ground-plugin/">Contact Shadow Ground Plugin</a></li>
<li><a href="./hdri-ground-plugin/">HDRi Ground Plugin <br/>(Projected Skybox)</a></li> <li><a href="./hdri-ground-plugin/">HDRi Ground Plugin <br/>(Projected Skybox)</a></li>
<li><a href="./obj-to-glb/">Convert OBJ to GLB </a></li> <li><a href="./obj-to-glb/">Convert OBJ to GLB </a></li>
<li><a href="./3dm-to-glb/">Convert 3DM to GLB </a></li> <li><a href="./3dm-to-glb/">Convert 3DM to GLB </a></li>
<li><a href="./hdr-to-exr/">Convert HDR to EXR </a></li> <li><a href="./hdr-to-exr/">Convert HDR to EXR </a></li>
<li><a href="./fat-lines/">Fat Lines <br/>(Mesh Lines) </a></li>
<li><a href="./fat-line-spiral/">Line Spiral<br/>(Mesh Lines) </a></li>
</ul>
<h2 class="category">Experiments</h2>
<ul>
<li><a href="./fat-lines/">Fat Lines (Mesh Lines) </a></li>
<li><a href="./fat-line-spiral/">Line Spiral (Mesh Lines) </a></li>
<li><a href="./progressive-hdr-shadows-exp/">Progressive HDR Environment Shadows</a></li> <li><a href="./progressive-hdr-shadows-exp/">Progressive HDR Environment Shadows</a></li>
<li><a href="./multi-render-uv-clip/">Multi-render UV clipping <br/> (Material Extension) </a></li> <li><a href="./multi-render-uv-clip/">Multi-render UV clipping <br/> (Material Extension) </a></li>
<li><a href="./svg-geometry-playground/">SVG Geometry Playground </a></li> <li><a href="./svg-geometry-playground/">SVG Geometry Playground </a></li>
<li><a href="./stencil-clipping-portal/">Stencil Clipping Portal </a></li>
<li><a href="./stencil-picking-outline/">Stencil Picking Outline </a></li>
</ul> </ul>
<h2 class="category">Shaders</h2> <h2 class="category">Shaders</h2>
<ul> <ul>

+ 37
- 0
examples/stencil-clipping-portal/index.html Visa fil

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stencil Clipping WebGL</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/global-loading.mjs"></script>
<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>

+ 87
- 0
examples/stencil-clipping-portal/script.ts Visa fil

import {
_testFinish,
_testStart,
IObject3D,
LoadingScreenPlugin,
OrbitControls3,
PickingPlugin,
ThreeViewer,
TransformControlsPlugin,
} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'
import * as THREE from 'threepipe'

async function init() {

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: false, // todo this is not working here, but its working in the other stencil example.
rgbm: true,
plugins: [LoadingScreenPlugin, PickingPlugin, TransformControlsPlugin],
stencil: true,
})

const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true))
ui.setupPlugins(PickingPlugin, TransformControlsPlugin)

await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', {
setBackground: true,
})
const result = await viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf', {
autoCenter: true,
autoScale: true,
})

const model = result?.getObjectByName('node_damagedHelmet_-6514')
const config = model?.uiConfig
if (config) ui.appendChild(config)

const maskMaterial = new THREE.MeshBasicMaterial({
color: 0x222222,
stencilRef: 1,
depthWrite: false,
stencilWrite: true,
depthTest: true,
stencilFunc: THREE.AlwaysStencilFunc,
stencilZPass: THREE.ReplaceStencilOp,
})
const maskPlane = new THREE.Mesh(new THREE.PlaneGeometry(4, 4), maskMaterial)
viewer.scene.addObject(maskPlane)

const maskCube = new THREE.Mesh(new THREE.BoxGeometry(4, 4, 20), new THREE.MeshBasicMaterial({
color: 0xffffff,
stencilRef: 1,
depthWrite: false,
stencilWrite: true,
depthTest: true,
stencilFunc: THREE.AlwaysStencilFunc,
stencilZPass: THREE.ReplaceStencilOp,
colorWrite:false,
}))
maskCube.userData.bboxVisible = false
maskCube.userData.userSelectable = false
maskCube.position.set(0, 0, 10)
viewer.scene.addObject(maskCube)
maskPlane.addEventListener('objectUpdate', ()=>{
maskCube.position.set(maskPlane.position.x, maskPlane.position.y, maskPlane.position.z + 10)
})

const mat = model?.materials?.[0]
if (mat && model) {
mat.stencilWrite = true
mat.stencilRef = 1
mat.stencilFunc = THREE.LessEqualStencilFunc
model.renderOrder = 2
model.position.z = -0.4
}

viewer.getPlugin(PickingPlugin)?.setSelectedObject(model)

const controls = viewer.scene.mainCamera.controls as OrbitControls3
controls.minAzimuthAngle = -1.5
controls.maxAzimuthAngle = 1.5

}

_testStart()
init().finally(_testFinish)

+ 37
- 0
examples/stencil-picking-outline/index.html Visa fil

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stencil Picking Outline</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/global-loading.mjs"></script>
<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>

+ 143
- 0
examples/stencil-picking-outline/script.ts Visa fil

import {
_testFinish,
_testStart,
AlwaysStencilFunc,
BufferGeometry2,
DecrementStencilOp,
EqualStencilFunc,
IObject3D,
LoadingScreenPlugin,
Mesh2,
PickingPlugin,
ReplaceStencilOp,
shaderReplaceString,
ThreeViewer,
TransformControlsPlugin,
UnlitMaterial,
} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'

// Custom outline for picking plugin by duplicating the model and using stencil buffer
async function init() {

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true,
rgbm: true,
plugins: [LoadingScreenPlugin, PickingPlugin, new TransformControlsPlugin(false)],
stencil: true,
})

const ui = viewer.addPluginSync(new TweakpaneUiPlugin(true))
ui.setupPlugins(TransformControlsPlugin, PickingPlugin)

await Promise.all([
viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', {
setBackground: false,
}),
viewer.load<IObject3D>('https://threejs.org/examples/models/gltf/kira.glb', {
autoCenter: true,
autoScale: true,
autoScaleRadius: 6,
}),
])

const selectionMaterial = new UnlitMaterial({
color: 0xe98a65,
stencilRef: 1,
depthWrite: false,
stencilWrite: true,
depthTest: true,
stencilFunc: AlwaysStencilFunc,
stencilZPass: ReplaceStencilOp,
colorWrite: true,
})
selectionMaterial.registerMaterialExtensions([{
shaderExtender:(shader, _material, _renderer) => {
shader.vertexShader = shaderReplaceString(
shader.vertexShader,
'#include <begin_vertex>',
'\ntransformed += normal * 0.02;',
{append: true}
)
},
isCompatible: ()=>true,
computeCacheKey: ()=> 'selectionMaterial',
}])
const selectionMesh = new Mesh2(new BufferGeometry2(), selectionMaterial)
const selectedObjectUpdateListener = (ev: {object: IObject3D})=>{
if (ev.object !== selected) return
selected.updateMatrixWorld()
selected.matrixWorld.decompose(
selectionMesh.position,
selectionMesh.quaternion,
selectionMesh.scale,
)
selectionMesh.updateMatrixWorld()
// const selectionScale = 1.1
// const center = new Box3B().expandByObject(selectionMesh).getCenter(new Vector3()).sub(selectionMesh.position)
// const m = new Matrix4().makeTranslation(new Vector3().copy(center).negate())
// .multiply(new Matrix4().makeScale(selectionScale, selectionScale, selectionScale))
// .multiply(new Matrix4().makeTranslation(new Vector3().copy(center).multiplyScalar(1 / selectionScale)))
// selectionMesh.matrix.premultiply(m).decompose(selectionMesh.position, selectionMesh.quaternion, selectionMesh.scale)
}
let selected = undefined as IObject3D | undefined
let lastState = null as any
viewer.getPlugin(PickingPlugin)!.addEventListener('selectedObjectChanged', ()=>{
const model = viewer.getPlugin(PickingPlugin)?.getSelectedObject<IObject3D>()
const geometry = model?.geometry
if (selected === model) return
if (selected) {
// remove selection mesh from previous selected object
selected.removeEventListener('objectUpdate', selectedObjectUpdateListener)
const lastMaterial = selected.materials?.[0]
if (lastMaterial && lastState) {
lastMaterial.stencilWrite = lastState.stencilWrite
lastMaterial.stencilRef = lastState.stencilRef
lastMaterial.stencilFunc = lastState.stencilFunc
lastMaterial.stencilZPass = lastState.stencilZPass
lastMaterial.needsUpdate = true
selected.renderOrder = lastState.renderOrder
}
lastState = null
}
const material = model?.materials?.[0]
if (!model?.isObject3D || !geometry || !material) { // it can also be a selected material
selectionMesh.geometry = undefined as any
selectionMesh.removeFromParent()
return
}
if (!geometry) return

// Set selected object's material to use stencil buffer
lastState = {
stencilWrite: material.stencilWrite,
stencilRef: material.stencilRef,
stencilFunc: material.stencilFunc,
stencilZPass: material.stencilZPass,
renderOrder: model.renderOrder,
}
material.stencilWrite = true
material.stencilRef = 1
material.stencilFunc = EqualStencilFunc
material.stencilZPass = DecrementStencilOp
material.needsUpdate = true
model.renderOrder = 2

// Set selection mesh to match selected object
selected = model
selectionMesh.geometry = geometry
// add listeners to update selection mesh position when its moved
selected.addEventListener('objectUpdate', selectedObjectUpdateListener)
selectedObjectUpdateListener({object: selected})

if (!selectionMesh.parent) viewer.scene.addObject(selectionMesh, {addToRoot: true}) // add to root so it is not saved
})
viewer.getPlugin(PickingPlugin)!.widgetEnabled = false

const chair = viewer.scene.getObjectByName('Node-Mesh003_1')
viewer.getPlugin(PickingPlugin)!.setSelectedObject(chair, true)
}

_testStart()
init().finally(_testFinish)

+ 3
- 2
src/rendering/RenderManager.ts Visa fil

// this._xrPreAnimationLoop = this._xrPreAnimationLoop.bind(this) // this._xrPreAnimationLoop = this._xrPreAnimationLoop.bind(this)
this._renderSize = new Vector2(canvas.clientWidth, canvas.clientHeight) this._renderSize = new Vector2(canvas.clientWidth, canvas.clientHeight)
this._renderScale = renderScale this._renderScale = renderScale
this._renderer = this._initWebGLRenderer(canvas, alpha)
this._renderer = this._initWebGLRenderer(canvas, alpha, targetOptions?.stencilBuffer ?? false)
this._context = this._renderer.getContext() this._context = this._renderer.getContext()
this._isWebGL2 = this._renderer.capabilities.isWebGL2 this._isWebGL2 = this._renderer.capabilities.isWebGL2
if (!this._isWebGL2) console.error('RenderManager: WebGL 1 is not officially supported anymore. Some features may not work.') if (!this._isWebGL2) console.error('RenderManager: WebGL 1 is not officially supported anymore. Some features may not work.')
// if (animationLoop) this.addEventListener('animationLoop', animationLoop) // todo: from viewer // if (animationLoop) this.addEventListener('animationLoop', animationLoop) // todo: from viewer
} }


protected _initWebGLRenderer(canvas: HTMLCanvasElement, alpha: boolean): IWebGLRenderer<this> {
protected _initWebGLRenderer(canvas: HTMLCanvasElement, alpha: boolean, stencil: boolean): IWebGLRenderer<this> {
const renderer = new WebGLRenderer({ const renderer = new WebGLRenderer({
canvas, canvas,
antialias: false, antialias: false,
premultipliedAlpha: false, // todo: see this, maybe use this with rgbm mode. premultipliedAlpha: false, // todo: see this, maybe use this with rgbm mode.
preserveDrawingBuffer: true, preserveDrawingBuffer: true,
powerPreference: RenderManager.POWER_PREFERENCE, powerPreference: RenderManager.POWER_PREFERENCE,
stencil,
}) })
// renderer.info.autoReset = false // Not supported by ExtendedRenderPass // renderer.info.autoReset = false // Not supported by ExtendedRenderPass



+ 7
- 0
src/rendering/RenderTarget.ts Visa fil

colorSpace?: ColorSpace colorSpace?: ColorSpace
type?: TextureDataType type?: TextureDataType
format?: number format?: number
/**
* @default true
*/
depthBuffer?: boolean depthBuffer?: boolean
/**
* @default false
*/
stencilBuffer?: boolean
depthTexture?: boolean depthTexture?: boolean
depthTextureType?: typeof UnsignedShortType | typeof UnsignedInt248Type | typeof UnsignedIntType | typeof FloatType depthTextureType?: typeof UnsignedShortType | typeof UnsignedInt248Type | typeof UnsignedIntType | typeof FloatType
depthTextureFormat?: typeof DepthFormat | typeof DepthStencilFormat depthTextureFormat?: typeof DepthFormat | typeof DepthStencilFormat

+ 2
- 1
src/rendering/RenderTargetManager.ts Visa fil

colorSpace = NoColorSpace, colorSpace = NoColorSpace,
type = UnsignedByteType, type = UnsignedByteType,
format = RGBAFormat, format = RGBAFormat,
stencilBuffer = false,
depthBuffer = true, depthBuffer = true,
depthTexture = false, depthTexture = false,
depthTextureType = UnsignedIntType, depthTextureType = UnsignedIntType,
height: size.height, height: size.height,
count: textureCount, count: textureCount,
} : size, } : size,
{samples, colorSpace, type, format, depthBuffer, depthTexture: depthTex},
{samples, colorSpace, type, format, depthBuffer, depthTexture: depthTex, stencilBuffer},
textureCount > 1 ? WebGLMultipleRenderTargets as any : WebGLRenderTarget) textureCount > 1 ? WebGLMultipleRenderTargets as any : WebGLRenderTarget)
this._processNewTarget(target, sizeMultiplier, trackTarget) this._processNewTarget(target, sizeMultiplier, trackTarget)
this._setTargetOptions(target, op) this._setTargetOptions(target, op)

+ 6
- 0
src/viewer/ThreeViewer.ts Visa fil

* @default 1 * @default 1
*/ */
modelRootScale?: number modelRootScale?: number
/**
* Enable stencil in renderer and stencilBuffer in composer render targets.
* @default false
*/
stencil?: boolean


debug?: boolean debug?: boolean


rgbm: options.rgbm ?? options.useRgbm ?? true, rgbm: options.rgbm ?? options.useRgbm ?? true,
zPrepass: options.zPrepass ?? options.useGBufferDepth ?? false, zPrepass: options.zPrepass ?? options.useGBufferDepth ?? false,
depthBuffer: !(options.zPrepass ?? options.useGBufferDepth ?? false), depthBuffer: !(options.zPrepass ?? options.useGBufferDepth ?? false),
stencilBuffer: options.stencil,
screenShader: options.screenShader, screenShader: options.screenShader,
renderScale: typeof options.renderScale === 'string' ? options.renderScale === 'auto' ? renderScale: typeof options.renderScale === 'string' ? options.renderScale === 'auto' ?
Math.min(options.maxRenderScale || 2, window.devicePixelRatio) : parseFloat(options.renderScale) : Math.min(options.maxRenderScale || 2, window.devicePixelRatio) : parseFloat(options.renderScale) :

+ 3
- 1
src/viewer/ViewerRenderManager.ts Visa fil

rgbm?: boolean, rgbm?: boolean,
msaa?: boolean | number, msaa?: boolean | number,
depthBuffer?: boolean, depthBuffer?: boolean,
stencilBuffer?: boolean,
zPrepass?: boolean, zPrepass?: boolean,
screenShader?: TViewerScreenShader screenShader?: TViewerScreenShader
maxHDRIntensity?: number maxHDRIntensity?: number


static DEFAULT_MSAA_SAMPLES = 4 static DEFAULT_MSAA_SAMPLES = 4


constructor({rgbm = true, msaa = false, depthBuffer = false, ...options}: ViewerRenderManagerOptions) {
constructor({rgbm = true, msaa = false, depthBuffer = true, stencilBuffer = false, ...options}: ViewerRenderManagerOptions) {
super({ super({
...options, ...options,
targetOptions: { targetOptions: {
colorSpace: rgbm ? RGBM16ColorSpace : NoColorSpace, colorSpace: rgbm ? RGBM16ColorSpace : NoColorSpace,
type: rgbm ? UnsignedByteType : HalfFloatType, type: rgbm ? UnsignedByteType : HalfFloatType,
depthBuffer: depthBuffer, depthBuffer: depthBuffer,
stencilBuffer: stencilBuffer,
generateMipmaps: /* msaa ? true : */false, // todo: hack for now, fix blurTransmissionTarget in ExtendedRenderPass generateMipmaps: /* msaa ? true : */false, // todo: hack for now, fix blurTransmissionTarget in ExtendedRenderPass
minFilter: /* msaa ? LinearMipMapLinearFilter : */LinearFilter, // todo: hack for now, fix blurTransmissionTarget in ExtendedRenderPass minFilter: /* msaa ? LinearMipMapLinearFilter : */LinearFilter, // todo: hack for now, fix blurTransmissionTarget in ExtendedRenderPass
}, },

Laddar…
Avbryt
Spara