mirror of
https://github.com/Doodle3D/Doodle3D-Core.git
synced 2024-12-22 11:03:48 +01:00
update render logic
This commit is contained in:
parent
8e76f3383c
commit
d4e1fd8e55
15
shaders/combine_frag.glsl
Normal file
15
shaders/combine_frag.glsl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
varying vec2 vUv;
|
||||||
|
uniform sampler2D tDiffuse;
|
||||||
|
uniform sampler2D uTexArray[1];
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 cDiffuse = texture2D(tDiffuse, vUv);
|
||||||
|
|
||||||
|
for (int i = 0; i < 1; i ++) {
|
||||||
|
vec4 cTex = texture2D(uTexArray[i], vUv);
|
||||||
|
cDiffuse = mix(cDiffuse, cTex, cTex.w);
|
||||||
|
// cDiffuse = cTex;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor = cDiffuse;
|
||||||
|
}
|
38
shaders/edge_frag.glsl
Normal file
38
shaders/edge_frag.glsl
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
uniform sampler2D tDiffuse;
|
||||||
|
uniform vec3 color;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
varying vec2 vUv;
|
||||||
|
|
||||||
|
vec3 hsv2rgb(vec3 c) {
|
||||||
|
vec4 K = vec4(1., 2. / 3., 1. / 3., 3.);
|
||||||
|
vec3 p = abs(fract(c.xxx + K.xyz) * 6. - K.www);
|
||||||
|
return c.z * mix(K.xxx, clamp(p - K.xxx, 0., 1.), c.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert depth to hue value so we can detect edges
|
||||||
|
vec3 depth(vec4 c) {
|
||||||
|
return hsv2rgb(vec3(c.z, 1., 1.)) * c.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
float cubicInOut(float t) {
|
||||||
|
return t < .5 ? 4. * pow(t, 3.) : .5 * pow(2. * t - 2., 3.) + 1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float x = 1. / resolution.x;
|
||||||
|
float y = 1. / resolution.y;
|
||||||
|
|
||||||
|
// lapace filter
|
||||||
|
vec4 f01 = texture2D(tDiffuse, vUv + vec2(0., -y));
|
||||||
|
vec4 f10 = texture2D(tDiffuse, vUv + vec2(-x, 0.));
|
||||||
|
vec4 f11 = texture2D(tDiffuse, vUv);
|
||||||
|
vec4 f12 = texture2D(tDiffuse, vUv + vec2(0., y));
|
||||||
|
vec4 f21 = texture2D(tDiffuse, vUv + vec2(x, 0.));
|
||||||
|
|
||||||
|
float depthLaplace = length(4. * depth(f11) - depth(f01) - depth(f10) - depth(f12) - depth(f21));
|
||||||
|
float normalLaplace = length(4. * f11.xy - f01.xy - f10.xy - f12.xy - f21.xy);
|
||||||
|
|
||||||
|
float edge = cubicInOut(depthLaplace) + cubicInOut(normalLaplace);
|
||||||
|
|
||||||
|
gl_FragColor = vec4(vec3(0.), edge);
|
||||||
|
}
|
6
shaders/edge_vert.glsl
Normal file
6
shaders/edge_vert.glsl
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
varying vec2 vUv;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vUv = uv;
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
uniform sampler2D tDiffuse;
|
|
||||||
uniform sampler2D tNormal;
|
|
||||||
uniform sampler2D tDepth;
|
|
||||||
uniform sampler2D tUI;
|
|
||||||
varying vec2 vUv;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 colorDiffuse = texture2D(tDiffuse, vUv); // cell shader
|
|
||||||
vec4 colorNormal = texture2D(tNormal, vUv); // outline from normal texture
|
|
||||||
colorNormal.w = 0.0;
|
|
||||||
vec4 colorDepth = texture2D(tDepth, vUv); // outline from depth texture
|
|
||||||
colorDepth.w = 0.0;
|
|
||||||
vec4 colorUI = texture2D(tUI, vUv); // color ui's
|
|
||||||
|
|
||||||
gl_FragColor = mix(max(colorDiffuse - colorDepth - colorNormal, 0.0), colorUI, colorUI.w);
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
uniform float mNear;
|
|
||||||
uniform float mFar;
|
|
||||||
uniform float opacity;
|
|
||||||
uniform float logDepthBufFC;
|
|
||||||
varying float vFragDepth;
|
|
||||||
|
|
||||||
#include <common>
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float fragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
|
|
||||||
float depth = fragDepthEXT / gl_FragCoord.w;
|
|
||||||
float color = 1.0 - smoothstep( mNear, mFar, depth );
|
|
||||||
gl_FragColor = vec4( vec3( color ), opacity );
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
uniform sampler2D tDiffuse;
|
|
||||||
uniform float threshold;
|
|
||||||
uniform vec2 aspect;
|
|
||||||
varying vec2 vUv;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float w = (1.0 / aspect.x);
|
|
||||||
float h = (1.0 / aspect.y);
|
|
||||||
|
|
||||||
vec4 n[9];
|
|
||||||
n[0] = texture2D(tDiffuse, vUv + vec2( -w, -h));
|
|
||||||
n[1] = texture2D(tDiffuse, vUv + vec2(0.0, -h));
|
|
||||||
n[2] = texture2D(tDiffuse, vUv + vec2( w, -h));
|
|
||||||
n[3] = texture2D(tDiffuse, vUv + vec2( -w, 0.0));
|
|
||||||
n[4] = texture2D(tDiffuse, vUv);
|
|
||||||
n[5] = texture2D(tDiffuse, vUv + vec2( w, 0.0));
|
|
||||||
n[6] = texture2D(tDiffuse, vUv + vec2( -w, h));
|
|
||||||
n[7] = texture2D(tDiffuse, vUv + vec2(0.0, h));
|
|
||||||
n[8] = texture2D(tDiffuse, vUv + vec2( w, h));
|
|
||||||
|
|
||||||
vec4 sobel_horizEdge = n[2] + (2.0 * n[5]) + n[8] - (n[0] + (2.0 * n[3]) + n[6]);
|
|
||||||
vec4 sobel_vertEdge = n[0] + (2.0 * n[1]) + n[2] - (n[6] + (2.0 * n[7]) + n[8]);
|
|
||||||
vec3 sobel = sqrt((sobel_horizEdge.rgb * sobel_horizEdge.rgb) + (sobel_vertEdge.rgb * sobel_vertEdge.rgb));
|
|
||||||
|
|
||||||
gl_FragColor = (length(sobel) > threshold) ? vec4(vec3(1.0), 0.0) : vec4(0.0);
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
// edge detection based on http://williamchyr.com/tag/unity/page/2/
|
|
||||||
uniform sampler2D tDiffuse;
|
|
||||||
uniform float threshold;
|
|
||||||
uniform vec2 aspect;
|
|
||||||
varying vec2 vUv;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float w = (1.0 / aspect.x);
|
|
||||||
float h = (1.0 / aspect.y);
|
|
||||||
|
|
||||||
vec4 a = texture2D(tDiffuse, vUv);
|
|
||||||
vec4 b = texture2D(tDiffuse, vUv + vec2(-w, -h));
|
|
||||||
vec4 c = texture2D(tDiffuse, vUv + vec2(w, -h));
|
|
||||||
vec4 d = texture2D(tDiffuse, vUv + vec2(-w, h));
|
|
||||||
vec4 e = texture2D(tDiffuse, vUv + vec2(w, h));
|
|
||||||
|
|
||||||
vec4 averageDepth = (b + c + d + e) / 4.0;
|
|
||||||
float difference = length(averageDepth - a);
|
|
||||||
|
|
||||||
gl_FragColor = difference > threshold ? vec4(vec3(1.0), 0.0) : vec4(0.0);
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
// edge detection based on http://williamchyr.com/tag/unity/page/2/
|
|
||||||
uniform sampler2D tDiffuse;
|
|
||||||
uniform float threshold;
|
|
||||||
uniform vec2 aspect;
|
|
||||||
varying vec2 vUv;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float w = (1.0 / aspect.x);
|
|
||||||
float h = (1.0 / aspect.y);
|
|
||||||
|
|
||||||
// vec4 a = texture2D(tDiffuse, vUv);
|
|
||||||
vec4 b = texture2D(tDiffuse, vUv + vec2(-w, -h));
|
|
||||||
vec4 c = texture2D(tDiffuse, vUv + vec2(w, -h));
|
|
||||||
vec4 d = texture2D(tDiffuse, vUv + vec2(-w, h));
|
|
||||||
vec4 e = texture2D(tDiffuse, vUv + vec2(w, h));
|
|
||||||
|
|
||||||
float difference = length(b - e) + length(c - d);
|
|
||||||
|
|
||||||
gl_FragColor = difference > threshold ? vec4(vec3(1.0), 0.0) : vec4(0.0);
|
|
||||||
}
|
|
9
shaders/normal_depth_frag.glsl
Normal file
9
shaders/normal_depth_frag.glsl
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
varying vec3 vNormal;
|
||||||
|
varying float vDepth;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 normal = vNormal.xy / 2. + .5;
|
||||||
|
float depth = mod(vDepth, 1.);
|
||||||
|
|
||||||
|
gl_FragColor = vec4(normal, depth, 1.);
|
||||||
|
}
|
10
shaders/normal_depth_vert.glsl
Normal file
10
shaders/normal_depth_vert.glsl
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
varying vec3 vNormal;
|
||||||
|
varying float vDepth;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vNormal = normalize(normalMatrix * normal);
|
||||||
|
vDepth = (projectionMatrix * modelViewMatrix * vec4(position, 1.0)).z / 30.;
|
||||||
|
|
||||||
|
#include <begin_vertex>
|
||||||
|
#include <project_vertex>
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
varying float vFragDepth;
|
|
||||||
uniform float logDepthBufFC;
|
|
||||||
|
|
||||||
#include <common>
|
|
||||||
#include <morphtarget_pars_vertex>
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
#include <begin_vertex>
|
|
||||||
#include <morphtarget_vertex>
|
|
||||||
#include <project_vertex>
|
|
||||||
|
|
||||||
// gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
|
|
||||||
vFragDepth = 1.0 + gl_Position.w;
|
|
||||||
}
|
|
@ -16,7 +16,6 @@ import TwistTransformer from '../d3/transformers/TwistTransformer.js';
|
|||||||
import SculptTransformer from '../d3/transformers/SculptTransformer.js';
|
import SculptTransformer from '../d3/transformers/SculptTransformer.js';
|
||||||
import StampTransformer from '../d3/transformers/StampTransformer.js';
|
import StampTransformer from '../d3/transformers/StampTransformer.js';
|
||||||
import SelectionBox from '../d3/SelectionBox.js';
|
import SelectionBox from '../d3/SelectionBox.js';
|
||||||
import ToonShaderRenderChain from '../d3/ToonShaderRenderChain';
|
|
||||||
import RenderChain from '../d3/RenderChain';
|
import RenderChain from '../d3/RenderChain';
|
||||||
import BaseTransformer from '../d3/transformers/BaseTransformer.js';
|
import BaseTransformer from '../d3/transformers/BaseTransformer.js';
|
||||||
import Camera from '../d3/Camera.js';
|
import Camera from '../d3/Camera.js';
|
||||||
@ -68,17 +67,12 @@ class D3Panel extends React.Component {
|
|||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.createScene();
|
this.createScene();
|
||||||
|
|
||||||
if (hasExtensionsFor.toonShaderPreview) {
|
this.renderChain = new RenderChain(this.renderer, this.scene, this.camera, hasExtensionsFor.toonShaderPreview, {
|
||||||
this.renderChain = new ToonShaderRenderChain(this.renderer, this.scene, this.camera, {
|
|
||||||
UI: this.UIContainer,
|
UI: this.UIContainer,
|
||||||
shapes: this.shapesManager,
|
shapes: this.shapesManager,
|
||||||
boundingBox: this.selectionBox,
|
boundingBox: this.selectionBox,
|
||||||
plane: this.plane
|
plane: this.plane
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.renderer.setClearColor(0xffffff);
|
|
||||||
this.renderChain = new RenderChain(this.renderer, this.scene, this.camera);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.DOM = null;
|
this.DOM = null;
|
||||||
}
|
}
|
||||||
@ -95,7 +89,7 @@ class D3Panel extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createScene() {
|
createScene() {
|
||||||
this.renderer = new THREE.WebGLRenderer();
|
this.renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true, preserveDrawingBuffer: true });
|
||||||
|
|
||||||
this.scene = new EventScene(this.renderer.domElement);
|
this.scene = new EventScene(this.renderer.domElement);
|
||||||
|
|
||||||
@ -224,7 +218,7 @@ class D3Panel extends React.Component {
|
|||||||
|
|
||||||
resizeHandler = (width, height) => {
|
resizeHandler = (width, height) => {
|
||||||
// set renderer size
|
// set renderer size
|
||||||
this.renderChain.setSize(width, height, PIXEL_RATIO);
|
this.renderChain.setSize(width, height, PIXEL_RATIO, false);
|
||||||
|
|
||||||
this.renderRequest();
|
this.renderRequest();
|
||||||
};
|
};
|
||||||
@ -249,7 +243,7 @@ class D3Panel extends React.Component {
|
|||||||
renderScene = () => {
|
renderScene = () => {
|
||||||
if (this.needRender) {
|
if (this.needRender) {
|
||||||
this.scene.updateMatrixWorld();
|
this.scene.updateMatrixWorld();
|
||||||
this.renderChain.render(true);
|
this.renderChain.render();
|
||||||
this.needRender = false;
|
this.needRender = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
73
src/d3/OutlinePass.js
vendored
Normal file
73
src/d3/OutlinePass.js
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
import normalDepthVert from '../../shaders/normal_depth_vert.glsl';
|
||||||
|
import normalDepthFrag from '../../shaders/normal_depth_frag.glsl';
|
||||||
|
import edgeVert from '../../shaders/edge_vert.glsl';
|
||||||
|
import edgeFrag from '../../shaders/edge_frag.glsl';
|
||||||
|
import combineVert from '../../shaders/combine_vert.glsl';
|
||||||
|
import combineFrag from '../../shaders/combine_frag.glsl';
|
||||||
|
|
||||||
|
export default class OutlinePass {
|
||||||
|
constructor(scene, camera, callbackBeforeRender) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.camera = camera;
|
||||||
|
this._callbackBeforeRender = callbackBeforeRender;
|
||||||
|
|
||||||
|
this.clear = true;
|
||||||
|
this.renderToScreen = false;
|
||||||
|
|
||||||
|
this._depthNormalRenderTarget = new THREE.WebGLRenderTarget();
|
||||||
|
this._edgeRenderTarget = new THREE.WebGLRenderTarget();
|
||||||
|
|
||||||
|
this._normalDepthMateral = new THREE.ShaderMaterial({
|
||||||
|
vertexShader: normalDepthVert,
|
||||||
|
fragmentShader: normalDepthFrag
|
||||||
|
});
|
||||||
|
|
||||||
|
this._edgeMaterial = new THREE.ShaderMaterial({
|
||||||
|
uniforms: {
|
||||||
|
"tDiffuse": { type: 't', value: this._depthNormalRenderTarget.texture },
|
||||||
|
"resolution": { type: 'v2', value: new THREE.Vector2() }
|
||||||
|
},
|
||||||
|
vertexShader: edgeVert,
|
||||||
|
fragmentShader: edgeFrag
|
||||||
|
});
|
||||||
|
|
||||||
|
this._copyEdge = new THREE.ShaderMaterial({
|
||||||
|
uniforms: {
|
||||||
|
"tDiffuse": { type: 't', value: null },
|
||||||
|
"uTexArray" : { type: 'tv', value: [this._edgeRenderTarget.texture] }
|
||||||
|
},
|
||||||
|
vertexShader: combineVert,
|
||||||
|
fragmentShader: combineFrag
|
||||||
|
})
|
||||||
|
|
||||||
|
this._camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
||||||
|
this._scene = new THREE.Scene();
|
||||||
|
this._quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2));
|
||||||
|
this._quad.frustumCulled = false;
|
||||||
|
this._scene.add(this._quad);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSize(width, height) {
|
||||||
|
this._depthNormalRenderTarget.setSize(width, height);
|
||||||
|
this._edgeRenderTarget.setSize(width, height);
|
||||||
|
this._edgeMaterial.uniforms.resolution.value.set(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(renderer, writeBuffer, readBuffer, delta, maskActive) {
|
||||||
|
if (this._callbackBeforeRender) this._callbackBeforeRender();
|
||||||
|
|
||||||
|
this._copyEdge.uniforms.tDiffuse.value = readBuffer.texture;
|
||||||
|
|
||||||
|
this.scene.overrideMaterial = this._normalDepthMateral;
|
||||||
|
renderer.render(this.scene, this.camera, this._depthNormalRenderTarget, true);
|
||||||
|
this._scene.overrideMaterial = this._edgeMaterial;
|
||||||
|
renderer.render(this._scene, this._camera, this._edgeRenderTarget, true);
|
||||||
|
|
||||||
|
this._scene.overrideMaterial = this._copyEdge;
|
||||||
|
renderer.render(this._scene, this._camera, this.renderToScreen ? null : writeBuffer, this.clear);
|
||||||
|
|
||||||
|
this.scene.overrideMaterial = null;
|
||||||
|
this._scene.overrideMaterial = null;
|
||||||
|
}
|
||||||
|
}
|
87
src/d3/RenderChain.js
vendored
87
src/d3/RenderChain.js
vendored
@ -1,19 +1,88 @@
|
|||||||
export default class RenderChain {
|
import * as THREE from 'three';
|
||||||
constructor(renderer, scene, camera) {
|
import OutlinePass from './OutlinePass.js';
|
||||||
this._renderer = renderer;
|
import RenderPass from './RenderPass.js';
|
||||||
this._scene = scene;
|
import 'three/examples/js/shaders/CopyShader.js';
|
||||||
this._camera = camera;
|
import 'three/examples/js/postprocessing/EffectComposer.js';
|
||||||
|
import 'three/examples/js/postprocessing/ShaderPass.js';
|
||||||
|
|
||||||
|
export default class RenderChain extends THREE.EffectComposer {
|
||||||
|
constructor(renderer, scene, camera, toonShader, groups) {
|
||||||
|
super(renderer);
|
||||||
|
this._groups = groups;
|
||||||
|
|
||||||
|
if (toonShader) {
|
||||||
|
const renderPass = new RenderPass(scene, camera, () => {
|
||||||
|
this._setVisible(this._initalValues, [groups.shapes, groups.plane, groups.boundingBox]);
|
||||||
|
});
|
||||||
|
this.addPass(renderPass);
|
||||||
|
|
||||||
|
const outlinePass = new OutlinePass(scene, camera, () => {
|
||||||
|
this._setVisible(this._initalValues, [groups.shapes]);
|
||||||
|
});
|
||||||
|
outlinePass.renderToScreen = true;
|
||||||
|
this.addPass(outlinePass);
|
||||||
|
|
||||||
|
const renderPassUI = new RenderPass(scene, camera, () => {
|
||||||
|
this._setVisible(this._initalValues, [groups.UI]);
|
||||||
|
});
|
||||||
|
renderPassUI.clear = false;
|
||||||
|
renderPassUI.renderToScreen = true;
|
||||||
|
this.addPass(renderPassUI);
|
||||||
|
} else {
|
||||||
|
const renderPass = new RenderPass(scene, camera);
|
||||||
|
renderPass.renderToScreen = true;
|
||||||
|
this.addPass(renderPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSize(width, height) {
|
this._renderer = renderer;
|
||||||
this._renderer.setSize(width, height);
|
this._camera = camera;
|
||||||
|
this._scene = scene;
|
||||||
|
this._toonShader = toonShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setSize(width, height, pixelRatio, rerender = true) {
|
||||||
|
this._renderer.setPixelRatio(pixelRatio);
|
||||||
|
this._renderer.setSize(width, height);
|
||||||
|
super.setSize(width * pixelRatio, height * pixelRatio);
|
||||||
|
|
||||||
// adjust aspect ratio of camera
|
|
||||||
this._camera.aspect = width / height;
|
this._camera.aspect = width / height;
|
||||||
this._camera.updateProjectionMatrix();
|
this._camera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
if (rerender) this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this._renderer.render(this._scene, this._camera);
|
if (this._toonShader) {
|
||||||
|
this._initalValues = this._getCurrentVisibleValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.render();
|
||||||
|
|
||||||
|
if (this._toonShader) {
|
||||||
|
const { shapes, UI, plane, boundingBox } = this._groups;
|
||||||
|
this._setVisible(this._initalValues, [shapes, UI, plane, boundingBox]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
src/d3/RenderPass.js
vendored
Normal file
31
src/d3/RenderPass.js
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
|
||||||
|
export default class RenderPass {
|
||||||
|
constructor(scene, camera, callbackBeforeRender) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.camera = camera;
|
||||||
|
this._callbackBeforeRender = callbackBeforeRender;
|
||||||
|
|
||||||
|
this.clear = true;
|
||||||
|
this.renderToScreen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSize(width, height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
render(renderer, writeBuffer, readBuffer, delta, maskActive) {
|
||||||
|
if (this._callbackBeforeRender) this._callbackBeforeRender();
|
||||||
|
|
||||||
|
let oldAutoClear;
|
||||||
|
if (this.clear === false) {
|
||||||
|
oldAutoClear = renderer.autoClear;
|
||||||
|
renderer.autoClear = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.render(this.scene, this.camera, this.renderToScreen ? null : readBuffer, this.clear);
|
||||||
|
|
||||||
|
if (this.clear === false) {
|
||||||
|
renderer.autoClear = oldAutoClear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
164
src/d3/ToonShaderRenderChain.js
vendored
164
src/d3/ToonShaderRenderChain.js
vendored
@ -1,164 +0,0 @@
|
|||||||
import * as THREE from 'three';
|
|
||||||
import 'three/examples/js/postprocessing/EffectComposer.js';
|
|
||||||
import 'three/examples/js/postprocessing/RenderPass.js';
|
|
||||||
import 'three/examples/js/postprocessing/ShaderPass.js';
|
|
||||||
import 'three/examples/js/shaders/CopyShader.js';
|
|
||||||
import vertexShaderPostprocessing from '../../shaders/vertexShaderPostprocessing.glsl';
|
|
||||||
import fragmentShaderSobelDepth from '../../shaders/fragmentShaderSobelDepth.glsl';
|
|
||||||
import fragmentShaderSobelNormal from '../../shaders/fragmentShaderSobelNormal.glsl';
|
|
||||||
import fragmentShaderCombineTextures from '../../shaders/fragmentShaderCombineTextures.glsl';
|
|
||||||
import fragmentShaderDepth from '../../shaders/fragmentShaderDepth.glsl';
|
|
||||||
import vertexShaderDepth from '../../shaders/vertexShaderDepth.glsl';
|
|
||||||
|
|
||||||
// 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]);
|
|
||||||
}
|
|
||||||
}
|
|
26
src/d3/createScene.js
vendored
26
src/d3/createScene.js
vendored
@ -1,6 +1,6 @@
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import ShapesManager from './ShapesManager.js';
|
import ShapesManager from './ShapesManager.js';
|
||||||
import ToonShaderRenderChain from './ToonShaderRenderChain.js';
|
import RenderChain from './RenderChain.js';
|
||||||
import { hasExtensionsFor } from '../utils/webGLSupport.js';
|
import { hasExtensionsFor } from '../utils/webGLSupport.js';
|
||||||
import { CANVAS_SIZE } from '../constants/d2Constants.js';
|
import { CANVAS_SIZE } from '../constants/d2Constants.js';
|
||||||
|
|
||||||
@ -43,32 +43,14 @@ export default function createScene(state, canvas) {
|
|||||||
const light = new THREE.AmbientLight(0x505050);
|
const light = new THREE.AmbientLight(0x505050);
|
||||||
scene.add(light);
|
scene.add(light);
|
||||||
|
|
||||||
let render;
|
const renderChain = new RenderChain(renderer, scene, camera, hasExtensionsFor.toonShaderThumbnail, {
|
||||||
let setSizeRenderer;
|
|
||||||
if (hasExtensionsFor.toonShaderThumbnail) {
|
|
||||||
const renderChain = new ToonShaderRenderChain(renderer, scene, camera, {
|
|
||||||
plane,
|
plane,
|
||||||
UI: new THREE.Object3D(),
|
UI: new THREE.Object3D(),
|
||||||
shapes: shapesManager,
|
shapes: shapesManager,
|
||||||
boundingBox: new THREE.Object3D()
|
boundingBox: new THREE.Object3D()
|
||||||
});
|
});
|
||||||
setSizeRenderer = renderChain.setSize.bind(renderChain);
|
const setSize = renderChain.setSize.bind(renderChain);
|
||||||
render = renderChain.render.bind(renderChain);
|
const render = renderChain.render.bind(renderChain);
|
||||||
} else {
|
|
||||||
renderer.setClearColor(0xffffff);
|
|
||||||
|
|
||||||
setSizeRenderer = renderer.setSize.bind(renderer);
|
|
||||||
render = renderer.render.bind(renderer, scene, camera);
|
|
||||||
}
|
|
||||||
|
|
||||||
const setSize = (width, height, pixelRatio) => {
|
|
||||||
setSizeRenderer(width, height, pixelRatio);
|
|
||||||
|
|
||||||
camera.aspect = width / height;
|
|
||||||
camera.updateProjectionMatrix();
|
|
||||||
|
|
||||||
render();
|
|
||||||
};
|
|
||||||
|
|
||||||
return { scene, camera, renderer, render, setSize };
|
return { scene, camera, renderer, render, setSize };
|
||||||
}
|
}
|
||||||
|
1
src/d3/index.js
vendored
1
src/d3/index.js
vendored
@ -1,7 +1,6 @@
|
|||||||
import createSceneData from './createSceneData.js';
|
import createSceneData from './createSceneData.js';
|
||||||
import createScene from './createScene.js';
|
import createScene from './createScene.js';
|
||||||
import RenderChain from './RenderChain.js';
|
import RenderChain from './RenderChain.js';
|
||||||
import ToonShaderRenderChain from './ToonShaderRenderChain.js';
|
|
||||||
import ShapeMesh from './ShapeMesh.js';
|
import ShapeMesh from './ShapeMesh.js';
|
||||||
import ShapesManager from './ShapesManager.js';
|
import ShapesManager from './ShapesManager.js';
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ export class CanvasPlane extends THREE.Mesh {
|
|||||||
const texture = new THREE.Texture(canvas);
|
const texture = new THREE.Texture(canvas);
|
||||||
const material = new THREE.MeshBasicMaterial({
|
const material = new THREE.MeshBasicMaterial({
|
||||||
map: texture,
|
map: texture,
|
||||||
|
depthTest: false,
|
||||||
side: THREE.DoubleSide
|
side: THREE.DoubleSide
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user