use matcap material

This commit is contained in:
casperlamboo 2017-11-23 17:29:56 +01:00
parent 9701bf0aa0
commit 4e37a4c4cf
8 changed files with 95 additions and 23 deletions

BIN
img/matcap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

29
shaders/matcap_frag.glsl Normal file
View File

@ -0,0 +1,29 @@
uniform float opacity;
uniform sampler2D tMatcap;
uniform vec3 color;
varying vec2 vNormal;
// color blending from https://www.w3.org/TR/compositing-1/#blendingcolor
float lum(vec3 c) {
return c.r * .3 + c.g * .59 + c.b * .11;
}
vec3 clipColor(vec3 c) {
float l = lum(c);
float n = min(min(c.r, c.g), c.b);
float x = max(max(c.r, c.g), c.b);
if (n < 0.) c = l + (((c - l) * l) / (l - n));
if (x > 1.) c = l + (((c - l) * (1. - l)) / (x - l));
return c;
}
vec3 setLum(vec3 c, float l) {
float d = l - lum(c);
return clipColor(c + d);
}
void main() {
vec4 matcap = texture2D(tMatcap, vNormal);
vec3 coloredMatcap = setLum(color, lum(matcap.rgb));
gl_FragColor = vec4(coloredMatcap, opacity);
}

8
shaders/matcap_vert.glsl Normal file
View File

@ -0,0 +1,8 @@
varying vec2 vNormal;
void main() {
vNormal = normalize(normalMatrix * normal).xy / 2. + .5;
#include <begin_vertex>
#include <project_vertex>
}

View File

@ -20,6 +20,7 @@ import RenderChain from '../d3/RenderChain';
import BaseTransformer from '../d3/transformers/BaseTransformer.js';
import Camera from '../d3/Camera.js';
import ReactResizeDetector from 'react-resize-detector';
import { load as loadMatcapMaterial } from '../d3/MatcapMaterial.js';
// import createDebug from 'debug';
// const debug = createDebug('d3d:d3');
@ -74,6 +75,7 @@ class D3Panel extends React.Component {
plane: this.plane
});
loadMatcapMaterial.then(this.renderRequest);
this.DOM = null;
}
@ -117,7 +119,7 @@ class D3Panel extends React.Component {
const ambientLight = new THREE.AmbientLight(0x505050);
this.scene.add(ambientLight);
this.shapesManager = new ShapesManager({ toonShader: hasExtensionsFor.toonShaderPreview });
this.shapesManager = new ShapesManager();
this.UIContainer = new EventObject3D();
this.UIContainer.matrixAutoUpdate = false;

View File

@ -8,6 +8,7 @@ import createScene from '../d3/createScene.js';
import injectSheet from 'react-jss';
import ReactResizeDetector from 'react-resize-detector';
import requestAnimationFrame from 'raf';
import { load as loadMatcapMaterial } from '../d3/MatcapMaterial.js';
const styles = {
container: {
@ -55,7 +56,9 @@ class DoodlePreview extends React.Component {
this.setState(scene);
this.editorControls = new THREE.EditorControls(scene.camera, canvas);
this.editorControls.addEventListener('change', () => scene.render());
this.editorControls.addEventListener('change', scene.render);
loadMatcapMaterial.then(scene.render;
}
componentWillUnmount() {

44
src/d3/MatcapMaterial.js vendored Normal file
View File

@ -0,0 +1,44 @@
import * as THREE from 'three';
import matcapVert from '../../shaders/matcap_vert.glsl';
import matcapFrag from '../../shaders/matcap_frag.glsl';
import matcapURL from '../../img/matcap.png';
let matcapTexture;
export const load = new Promise((resolve, reject) => {
matcapTexture = new THREE.TextureLoader().load(matcapURL, resolve, () => {}, reject);
});
export default class MatcapMaterial extends THREE.ShaderMaterial {
constructor({ color = new THREE.Color(), opacity = 1 }) {
super({
uniforms: {
"opacity": { type: 'f', value: opacity },
"tMatcap": { type: 't', value: matcapTexture },
"color": { type: 'vec3', value: new THREE.Vector3() }
},
vertexShader: matcapVert,
fragmentShader: matcapFrag
});
this.color = color;
this.side = THREE.DoubleSide;
}
set color(color) {
this.uniforms.color.value.fromArray(color.toArray());
return color;
}
get color() {
return new THREE.Color().fromArray(this.uniforms.color.value.toArray());
}
set opacity(opacity) {
if (!this.uniforms) return opacity;
return this.uniforms.opacity.value = opacity;
}
clone() {
return new MatcapMaterial({ color: this.color, opacity: this.uniforms.opacity.value });
}
}

22
src/d3/ShapeMesh.js vendored
View File

@ -3,6 +3,7 @@ import { applyMatrixOnPath } from '../utils/vectorUtils.js';
import { shapeToPointsCornered } from '../shape/shapeToPoints.js';
import * as THREE from 'three';
import { getPointsBounds, shapeChanged } from '../shape/shapeDataUtils.js';
import MatcapMaterial from './MatcapMaterial.js';
import { DESELECT_TRANSPARENCY, LEGACY_HEIGHT_STEP } from '../constants/d3Constants.js';
import ThreeBSP from 'three-js-csg';
@ -16,32 +17,18 @@ const MAX_HEIGHT_BASE = 5;
const isValidNumber = (num) => typeof num === 'number' && !isNaN(num);
class ShapeMesh extends THREE.Object3D {
constructor(shapeData, active, toonShader) {
constructor(shapeData, active) {
super();
this.name = shapeData.UID;
const { sculpt, rotate, twist, height, type, transform, z, color, fill, solid } = shapeData;
let material;
if (toonShader) {
material = new THREE.MeshToonMaterial({
color: new THREE.Color(color),
shading: THREE.SmoothShading,
side: THREE.DoubleSide
});
} else {
material = new THREE.MeshLambertMaterial({
color: new THREE.Color(color),
side: THREE.DoubleSide
});
}
const material = new MatcapMaterial({ color: new THREE.Color(color) });
this._mesh = new THREE.Mesh(new THREE.BufferGeometry(), material.clone());
this._mesh.name = shapeData.UID;
this._mesh.isShapeMesh = true;
this._toonShader = toonShader;
this._shapes = [];
this._shapesMap = [];
@ -221,7 +208,8 @@ class ShapeMesh extends THREE.Object3D {
throw new Error(`Cannot update object ${this.name}: color is an invalid value.`);
}
this._holeMesh.material.color.setHex(color);
this._mesh.material.color = new THREE.Color(color);
this._holeMesh.material.color = new THREE.Color(color);
this._color = color;
}

View File

@ -7,11 +7,9 @@ import ThreeBSP from 'three-js-csg';
const THREE_BSP = ThreeBSP(THREE);
export default class ShapesManager extends THREE.Object3D {
constructor({ toonShader }) {
constructor() {
super();
this._toonShader = toonShader;
this._meshes = {};
this._spaces = {};
this.name = 'shapes-manager';
@ -137,7 +135,7 @@ export default class ShapesManager extends THREE.Object3D {
_handleShapeAdded(shapeData, active) {
if (!SHAPE_TYPE_PROPERTIES[shapeData.type].D3Visible) return;
const { space } = shapeData;
const mesh = new ShapeMesh(shapeData, active, this._toonShader);
const mesh = new ShapeMesh(shapeData, active);
this._meshes[shapeData.UID] = { mesh, space };
this._spaces[space].add(mesh);