<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
body {
background-color: #000;
margin: 0px;
overflow: hidden;
}
var mesh, renderer, scene, camera, controls;
//loader.load('https://threejs.org/examples/textures/brick_diffuse.jpg')
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.gammaFactor = 2.2;
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 2, 2, 4 );
camera.lookAt(new THREE.Vector3(0,0,0));
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
// ambient light
//scene.add( new THREE.AmbientLight( 0x222222 ) );
// directional light
var light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 80, 80, 80 );
scene.add( light );
// axes
scene.add( new THREE.AxesHelper( 20 ) );
// geometry
var geometry = new THREE.TorusKnotBufferGeometry( 1, 0.3, 128, 22 );
// https://github.com/Fyrestar/THREE.extendMaterial
var material = THREE.extendMaterial(THREE.MeshStandardMaterial, {
// Will be prepended to vertex and fragment code
header: 'varying vec3 vNN; varying vec3 vEye;',
// Insert code lines by hinting at a existing
vertex: {
// Inserts the line after #include <fog_vertex>
'#include <fog_vertex>': `
mat4 LM = modelMatrix;
LM[2][3] = 0.0;
LM[3][0] = 0.0;
LM[3][1] = 0.0;
LM[3][2] = 0.0;
vec4 GN = LM * vec4(objectNormal.xyz, 1.0);
vNN = normalize(GN.xyz);
vEye = normalize(GN.xyz-cameraPosition);`
},
fragmentHeader: `
uniform vec3 skinTone;
`,
fragment: {
'?gl_FragColor = vec4( outgoingLight, diffuseColor.a );': `
float skinShadow = 1.0 - length( outgoingLight.rgb ) ;
outgoingLight += skinShadow * blood * fresnel;
`,
'?#include <emissivemap_fragment>' : `
const vec3 blood = vec3( 0.15, 0.02, 0.03 );
diffuseColor.rgb = skinTone;
float bri = ( length( diffuseColor.rgb ) );
vec3 subtone = diffuseColor.rgb * bri;
vec3 fronttone = diffuseColor.rgb;
subtone *= vec3( 1.0 ) + blood;
float fresnel = ( 1.0 - -min(dot(vEye, normalize(vNN) ), 0.0 ) );
float sublit = pow( fresnel, 2.0 );
float frontlit = ( 1.0 - sublit );
diffuseColor.rgb *= sublit * subtone * subtone + frontlit * fronttone;
diffuseColor.rgb += ( subtone * subtone ) * frontlit;
`
},
// Uniforms (will be applied to existing or added)
uniforms: {
metalness: 0.25,
roughness: 0.75,
diffuse: new THREE.Color( 'black' ),
skinTone: new THREE.Color( '#ba9b80'),
specular: new THREE.Color( 'white' )
}
});
const gui = new dat.GUI();
const pars = {
color: {
value: 0xba9b80
}
}
gui.addColor( pars.color, "value").name("Color").onChange( function() { material.uniforms.skinTone.value.set( pars.color.value ); } );;
// mesh
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
sk.edit( material, true );
function animate() {
mesh.rotateY(0.02);
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
View Compiled
This Pen doesn't use any external CSS resources.