mirror of
https://github.com/Doodle3D/Doodle3D-Core.git
synced 2024-11-16 19:17:56 +01:00
165 lines
5.3 KiB
JavaScript
165 lines
5.3 KiB
JavaScript
|
import * as THREE from 'three';
|
||
|
import 'three/examples/js/postprocessing/EffectComposer';
|
||
|
import 'three/examples/js/postprocessing/RenderPass';
|
||
|
import 'three/examples/js/postprocessing/ShaderPass';
|
||
|
import 'three/examples/js/shaders/CopyShader';
|
||
|
import vertexShaderPostprocessing from './shaders/vertexShaderPostprocessing.js';
|
||
|
import fragmentShaderSobelDepth from './shaders/fragmentShaderSobelDepth.js';
|
||
|
import fragmentShaderSobelNormal from './shaders/fragmentShaderSobelNormal.js';
|
||
|
import fragmentShaderCombineTextures from './shaders/fragmentShaderCombineTextures.js';
|
||
|
import fragmentShaderDepth from './shaders/fragmentShaderDepth.js';
|
||
|
import vertexShaderDepth from './shaders/vertexShaderDepth.js';
|
||
|
|
||
|
// Based on Doodle3D/Toon-Shader
|
||
|
|
||
|
// initize render targets with default canvas size
|
||
|
const DEFAULT_WIDTH = 300;
|
||
|
const DEFAULT_HEIGHT = 200;
|
||
|
|
||
|
const NORMAL_MATERIAL = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide });
|
||
|
const DEPTH_MATERIAL = new THREE.ShaderMaterial({
|
||
|
uniforms: {
|
||
|
mNear: { type: 'f', value: 1.0 },
|
||
|
mFar: { type: 'f', value: 3000.0 },
|
||
|
opacity: { type: 'f', value: 1.0 },
|
||
|
logDepthBufFC: { type: 'f', value: 2.0 }
|
||
|
},
|
||
|
vertexShader: vertexShaderDepth,
|
||
|
fragmentShader: fragmentShaderDepth,
|
||
|
side: THREE.DoubleSide
|
||
|
});
|
||
|
|
||
|
export default class Composer {
|
||
|
constructor(renderer, scene, camera, groups) {
|
||
|
this._renderer = renderer;
|
||
|
this._scene = scene;
|
||
|
this._camera = camera;
|
||
|
this._groups = groups;
|
||
|
|
||
|
this._aspect = new THREE.Vector2(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||
|
|
||
|
const {
|
||
|
composer: composerDepth,
|
||
|
renderTarget: renderTargetDepth
|
||
|
} = this._createSobelComposer(DEPTH_MATERIAL, 0.005, fragmentShaderSobelDepth);
|
||
|
|
||
|
this._composerDepth = composerDepth;
|
||
|
|
||
|
const {
|
||
|
composer: composerNormal,
|
||
|
renderTarget: renderTargetNormal
|
||
|
} = this._createSobelComposer(NORMAL_MATERIAL, 0.5, fragmentShaderSobelNormal);
|
||
|
|
||
|
this._composerNormal = composerNormal;
|
||
|
|
||
|
const renderTargetUI = new THREE.WebGLRenderTarget(DEFAULT_WIDTH, DEFAULT_HEIGHT, {
|
||
|
format: THREE.RGBAFormat
|
||
|
});
|
||
|
this._composerUI = new THREE.EffectComposer(this._renderer, renderTargetUI);
|
||
|
this._composerUI.addPass(new THREE.RenderPass(scene, camera));
|
||
|
this._composerUI.addPass(new THREE.ShaderPass(THREE.CopyShader));
|
||
|
|
||
|
this._composer = new THREE.EffectComposer(renderer);
|
||
|
this._composer.addPass(new THREE.RenderPass(scene, camera, undefined, new THREE.Color(0xffffff), 1.0));
|
||
|
const combineComposers = new THREE.ShaderPass(new THREE.ShaderMaterial({
|
||
|
uniforms: {
|
||
|
tDiffuse: { type: 't' },
|
||
|
tNormal: { type: 't', value: renderTargetNormal.texture },
|
||
|
tDepth: { type: 't', value: renderTargetDepth.texture },
|
||
|
tUI: { type: 't', value: renderTargetUI.texture }
|
||
|
},
|
||
|
vertexShader: vertexShaderPostprocessing,
|
||
|
fragmentShader: fragmentShaderCombineTextures
|
||
|
}));
|
||
|
combineComposers.renderToScreen = true;
|
||
|
this._composer.addPass(combineComposers);
|
||
|
}
|
||
|
|
||
|
_createSobelComposer(material, threshold, fragmentShader) {
|
||
|
const renderTarget = new THREE.WebGLRenderTarget(DEFAULT_WIDTH, DEFAULT_HEIGHT, {
|
||
|
format: THREE.RGBFormat
|
||
|
});
|
||
|
|
||
|
const composer = new THREE.EffectComposer(this._renderer, renderTarget);
|
||
|
|
||
|
composer.addPass(new THREE.RenderPass(this._scene, this._camera, material));
|
||
|
|
||
|
const sobelShader = new THREE.ShaderPass(new THREE.ShaderMaterial({
|
||
|
uniforms: {
|
||
|
tDiffuse: { type: 't' },
|
||
|
threshold: { type: 'f', value: threshold },
|
||
|
aspect: { type: 'v2', value: this._aspect }
|
||
|
},
|
||
|
vertexShader: vertexShaderPostprocessing,
|
||
|
fragmentShader
|
||
|
}));
|
||
|
composer.addPass(sobelShader);
|
||
|
|
||
|
composer.addPass(new THREE.ShaderPass(THREE.CopyShader));
|
||
|
|
||
|
return { renderTarget, composer };
|
||
|
}
|
||
|
|
||
|
setSize(width, height, pixelRatio) {
|
||
|
this._renderer.setPixelRatio(pixelRatio);
|
||
|
this._renderer.setSize(width, height);
|
||
|
|
||
|
this._aspect.set(width, height);
|
||
|
|
||
|
// adjust aspect ratio of camera
|
||
|
this._camera.aspect = width / height;
|
||
|
this._camera.updateProjectionMatrix();
|
||
|
|
||
|
width *= pixelRatio;
|
||
|
height *= pixelRatio;
|
||
|
|
||
|
this._composer.setSize(width, height);
|
||
|
this._composerNormal.setSize(width, height);
|
||
|
this._composerDepth.setSize(width, height);
|
||
|
this._composerUI.setSize(width, height);
|
||
|
}
|
||
|
|
||
|
getCurrentVisibleValues() {
|
||
|
const visibleValues = {};
|
||
|
|
||
|
for (const key in this._groups) {
|
||
|
visibleValues[key] = this._groups[key].visible;
|
||
|
}
|
||
|
|
||
|
return visibleValues;
|
||
|
}
|
||
|
|
||
|
setVisible(initalValues, visibleGroups) {
|
||
|
for (const key in this._groups) {
|
||
|
const group = this._groups[key];
|
||
|
|
||
|
if (visibleGroups.indexOf(group) !== -1) {
|
||
|
group.visible = initalValues[key];
|
||
|
} else {
|
||
|
group.visible = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
const initalValues = this.getCurrentVisibleValues();
|
||
|
|
||
|
const shapes = this._groups.shapes;
|
||
|
const UI = this._groups.UI;
|
||
|
const plane = this._groups.plane;
|
||
|
const boundingBox = this._groups.boundingBox;
|
||
|
|
||
|
this.setVisible(initalValues, [shapes]);
|
||
|
this._composerDepth.render();
|
||
|
this._composerNormal.render();
|
||
|
|
||
|
this.setVisible(initalValues, [UI]);
|
||
|
this._composerUI.render();
|
||
|
|
||
|
this.setVisible(initalValues, [shapes, plane, boundingBox]);
|
||
|
this._composer.render();
|
||
|
|
||
|
this.setVisible(initalValues, [shapes, UI, plane, boundingBox]);
|
||
|
}
|
||
|
}
|