<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
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.com/three@0.129.0
  2. https://threejs.org/examples/js/controls/OrbitControls.js
  3. https://threejs.org/examples/js/controls/TransformControls.js
  4. https://mevedia.com/share/ExtendMaterial.js
  5. https://mevedia.com/share/ShaderKit.min.js?v1