polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
135 lines (121 loc) • 4.29 kB
text/typescript
/**
* Allows to compose two different renders.
*
*
*/
import {TypedPostProcessNode, TypedPostNodeContext} from './_Base';
import {Pass} from '../../../modules/three/examples/jsm/postprocessing/Pass';
import {NodeParamsConfig} from '../utils/params/ParamsConfig';
import {EffectComposer} from '../../../modules/three/examples/jsm/postprocessing/EffectComposer';
import {WebGLRenderer} from 'three/src/renderers/WebGLRenderer';
import {WebGLRenderTarget} from 'three/src/renderers/WebGLRenderTarget';
import {LinearFilter, RGBAFormat} from 'three/src/constants';
import {ShaderMaterial} from 'three/src/materials/ShaderMaterial';
import {UniformsUtils} from 'three/src/renderers/shaders/UniformsUtils';
import {IUniformV2, IUniformN, IUniformTexture} from '../utils/code/gl/Uniforms';
import VERTEX from './gl/default.vert.glsl';
import FRAGMENT from './gl/Layer.frag.glsl';
import {Poly} from '../../Poly';
interface LayerUniforms {
// tDiffuse: IUniformTexture;
texture1: IUniformTexture;
texture2: IUniformTexture;
delta: IUniformV2;
h: IUniformN;
}
// const FRAGMENT = `
// #include <common>
// uniform sampler2D tDiffuse;
// varying vec2 vUv;
// void main() {
// gl_FragColor = texture2D( tDiffuse, vUv);
// }`;
const SHADER = {
uniforms: {
tDiffuse: {value: null},
texture1: {value: null},
texture2: {value: null},
h: {value: 1.0 / 512.0},
},
vertexShader: VERTEX,
fragmentShader: FRAGMENT,
};
class LayerPass extends Pass {
private material: ShaderMaterial;
private uniforms: LayerUniforms;
private fsQuad: Pass.FullScreenQuad;
constructor(private _composer1: EffectComposer, private _composer2: EffectComposer) {
super();
this.uniforms = UniformsUtils.clone(SHADER.uniforms);
this.material = new ShaderMaterial({
uniforms: this.uniforms as any,
vertexShader: SHADER.vertexShader,
fragmentShader: SHADER.fragmentShader,
transparent: true,
});
this.fsQuad = new Pass.FullScreenQuad(this.material);
}
render(renderer: WebGLRenderer, writeBuffer: WebGLRenderTarget) {
this._composer1.render();
this._composer2.render();
// this.uniforms.texture1.value = this._composer1.writeBuffer.texture;
// this.uniforms.texture2.value = this._composer2.writeBuffer.texture;
this.uniforms.texture1.value = this._composer1.readBuffer.texture;
this.uniforms.texture2.value = this._composer2.readBuffer.texture;
if (this.renderToScreen) {
renderer.setRenderTarget(null);
this.fsQuad.render(renderer);
} else {
renderer.setRenderTarget(writeBuffer);
if (this.clear) renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil);
this.fsQuad.render(renderer);
}
}
}
class LayerPostParamsConfig extends NodeParamsConfig {}
const ParamsConfig = new LayerPostParamsConfig();
export class LayerPostNode extends TypedPostProcessNode<LayerPass, LayerPostParamsConfig> {
params_config = ParamsConfig;
static type() {
return 'layer';
}
initializeNode() {
super.initializeNode();
this.io.inputs.setCount(2);
}
setup_composer(context: TypedPostNodeContext): void {
const renderer = context.composer.renderer;
const parameters = {
minFilter: LinearFilter,
magFilter: LinearFilter,
format: RGBAFormat,
stencilBuffer: true,
};
const render_target1 = Poly.renderersController.renderTarget(
renderer.domElement.offsetWidth,
renderer.domElement.offsetHeight,
parameters
);
const render_target2 = Poly.renderersController.renderTarget(
renderer.domElement.offsetWidth,
renderer.domElement.offsetHeight,
parameters
);
const composer1 = new EffectComposer(renderer, render_target1);
const composer2 = new EffectComposer(renderer, render_target2);
// renderToScreen = false to ensure the last pass of each composer is still
// written to the render_target
composer1.renderToScreen = false;
composer2.renderToScreen = false;
const cloned_context1 = {...context};
const cloned_context2 = {...context};
cloned_context1.composer = composer1;
cloned_context2.composer = composer2;
this._add_pass_from_input(0, cloned_context1);
this._add_pass_from_input(1, cloned_context2);
const pass = new LayerPass(composer1, composer2);
this.update_pass(pass);
context.composer.addPass(pass);
}
update_pass(pass: LayerPass) {}
}