123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- ;(function () {
- class EffectComposer {
- constructor(renderer, renderTarget) {
- this.renderer = renderer
- if (renderTarget === undefined) {
- const size = renderer.getSize(new THREE.Vector2())
- this._pixelRatio = renderer.getPixelRatio()
- this._width = size.width
- this._height = size.height
- renderTarget = new THREE.WebGLRenderTarget(this._width * this._pixelRatio, this._height * this._pixelRatio)
- renderTarget.texture.name = 'EffectComposer.rt1'
- } else {
- this._pixelRatio = 1
- this._width = renderTarget.width
- this._height = renderTarget.height
- }
- this.renderTarget1 = renderTarget
- this.renderTarget2 = renderTarget.clone()
- this.renderTarget2.texture.name = 'EffectComposer.rt2'
- this.writeBuffer = this.renderTarget1
- this.readBuffer = this.renderTarget2
- this.renderToScreen = true
- this.passes = [] // dependencies
- if (THREE.CopyShader === undefined) {
- console.error('THREE.EffectComposer relies on THREE.CopyShader')
- }
- if (THREE.ShaderPass === undefined) {
- console.error('THREE.EffectComposer relies on THREE.ShaderPass')
- }
- this.copyPass = new THREE.ShaderPass(THREE.CopyShader)
- this.clock = new THREE.Clock()
- }
- swapBuffers() {
- const tmp = this.readBuffer
- this.readBuffer = this.writeBuffer
- this.writeBuffer = tmp
- }
- addPass(pass) {
- this.passes.push(pass)
- pass.setSize(this._width * this._pixelRatio, this._height * this._pixelRatio)
- }
- insertPass(pass, index) {
- this.passes.splice(index, 0, pass)
- pass.setSize(this._width * this._pixelRatio, this._height * this._pixelRatio)
- }
- removePass(pass) {
- const index = this.passes.indexOf(pass)
- if (index !== -1) {
- this.passes.splice(index, 1)
- }
- }
- isLastEnabledPass(passIndex) {
- for (let i = passIndex + 1; i < this.passes.length; i++) {
- if (this.passes[i].enabled) {
- return false
- }
- }
- return true
- }
- render(deltaTime) {
- // deltaTime value is in seconds
- if (deltaTime === undefined) {
- deltaTime = this.clock.getDelta()
- }
- const currentRenderTarget = this.renderer.getRenderTarget()
- let maskActive = false
- for (let i = 0, il = this.passes.length; i < il; i++) {
- const pass = this.passes[i]
- if (pass.enabled === false) continue
- pass.renderToScreen = this.renderToScreen && this.isLastEnabledPass(i)
- pass.render(this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive)
- if (pass.needsSwap) {
- if (maskActive) {
- const context = this.renderer.getContext()
- const stencil = this.renderer.state.buffers.stencil //context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
- stencil.setFunc(context.NOTEQUAL, 1, 0xffffffff)
- this.copyPass.render(this.renderer, this.writeBuffer, this.readBuffer, deltaTime) //context.stencilFunc( context.EQUAL, 1, 0xffffffff );
- stencil.setFunc(context.EQUAL, 1, 0xffffffff)
- }
- this.swapBuffers()
- }
- if (THREE.MaskPass !== undefined) {
- if (pass instanceof THREE.MaskPass) {
- maskActive = true
- } else if (pass instanceof THREE.ClearMaskPass) {
- maskActive = false
- }
- }
- }
- this.renderer.setRenderTarget(currentRenderTarget)
- }
- reset(renderTarget) {
- if (renderTarget === undefined) {
- const size = this.renderer.getSize(new THREE.Vector2())
- this._pixelRatio = this.renderer.getPixelRatio()
- this._width = size.width
- this._height = size.height
- renderTarget = this.renderTarget1.clone()
- renderTarget.setSize(this._width * this._pixelRatio, this._height * this._pixelRatio)
- }
- this.renderTarget1.dispose()
- this.renderTarget2.dispose()
- this.renderTarget1 = renderTarget
- this.renderTarget2 = renderTarget.clone()
- this.writeBuffer = this.renderTarget1
- this.readBuffer = this.renderTarget2
- }
- setSize(width, height) {
- this._width = width
- this._height = height
- const effectiveWidth = this._width * this._pixelRatio
- const effectiveHeight = this._height * this._pixelRatio
- this.renderTarget1.setSize(effectiveWidth, effectiveHeight)
- this.renderTarget2.setSize(effectiveWidth, effectiveHeight)
- for (let i = 0; i < this.passes.length; i++) {
- this.passes[i].setSize(effectiveWidth, effectiveHeight)
- }
- }
- setPixelRatio(pixelRatio) {
- this._pixelRatio = pixelRatio
- this.setSize(this._width, this._height)
- }
- }
- class Pass {
- constructor() {
- // if set to true, the pass is processed by the composer
- this.enabled = true // if set to true, the pass indicates to swap read and write buffer after rendering
- this.needsSwap = true // if set to true, the pass clears its buffer before rendering
- this.clear = false // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer.
- this.renderToScreen = false
- }
- setSize() {}
- render() {
- console.error('THREE.Pass: .render() must be implemented in derived pass.')
- }
- } // Helper for passes that need to fill the viewport with a single quad.
- const _camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1) // https://github.com/mrdoob/three.js/pull/21358
- const _geometry = new THREE.BufferGeometry()
- _geometry.setAttribute('position', new THREE.Float32BufferAttribute([-1, 3, 0, -1, -1, 0, 3, -1, 0], 3))
- _geometry.setAttribute('uv', new THREE.Float32BufferAttribute([0, 2, 0, 0, 2, 0], 2))
- class FullScreenQuad {
- constructor(material) {
- this._mesh = new THREE.Mesh(_geometry, material)
- }
- dispose() {
- this._mesh.geometry.dispose()
- }
- render(renderer) {
- renderer.render(this._mesh, _camera)
- }
- get material() {
- return this._mesh.material
- }
- set material(value) {
- this._mesh.material = value
- }
- }
- THREE.EffectComposer = EffectComposer
- THREE.FullScreenQuad = FullScreenQuad
- THREE.Pass = Pass
- })()
|