0

In my scene I render complex objects, which have a complex surface structure. Furthermore I am not using light in my scene and I am trying to avoid it.

For now I am using the MeshNormalMaterial which shows perfectly the surface structures of my objects.

object with MeshNormalMaterial: object with MeshNormalMaterial

But I want to render certain objects with a unique color (e.g. from dark red to light red based on the surface structure/ similar to the MeshNormalMaterial).


I tried the MeshDepthMaterial for one object, but it rendered the whole object in almost color (no/ sparse color gradation) and not as expected like in this example. Independent of the camera position.

Same object from above with: MeshDepthMaterial same object with MeshDepthMaterial


I am using a THREE.PerspectiveCamera with THREE.OrbitControls. Camera properties:

//camera attributes
  public fieldOfView: number = 60;
  public nearClippingPane: number = 0.1;
  public farClippingPane: number = 50000;

Does the MeshNormalMaterial require light or why is this the case? Can I somehow amplify the depth effect of MeshNormalMaterial?

Is ist possible to restrict the RGB Colors of MeshNormalMaterial or do I have to use another Material for my purpose?

d4rty
  • 3,970
  • 5
  • 34
  • 73

1 Answers1

1

I just slightly modified the code of the fragment shader from this SO answer, so all credits to Rabbid76:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.01, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);

var colors = {
  color1: "#ff0000",
  color2: "#ffaaaa"
}

var geometry = new THREE.TorusKnotBufferGeometry(2, 0.5, 100, 16);
var material = new THREE.ShaderMaterial({
  uniforms: {
    color1: {
      value: new THREE.Color(colors.color1)
    },
    color2: {
      value: new THREE.Color(colors.color2)
    }
  },
  vertexShader: vertShader,
  fragmentShader: fragShader
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

var gui = new dat.GUI();
gui.addColor(colors, "color1").onChange(function(value) {
  material.uniforms.color1.value.set(value);
});
gui.addColor(colors, "color2").onChange(function(value) {
  material.uniforms.color2.value.set(value);
});

render();

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
<script>
  var vertShader = `
  varying vec3 vNormal;

  void main(void)
  {
      vNormal      = normalMatrix * normalize(normal); 
      gl_Position  = projectionMatrix * modelViewMatrix * vec4(position,1.0);
  }
  `;

  var fragShader = `
  uniform vec3 color1;
  uniform vec3 color2;
  
  varying vec3 vNormal;

  void main(void)
  {
      vec3 view_nv  = normalize(vNormal);
      vec3 nv_color = view_nv * 0.5 + 0.5;
      vec3 c = mix(color1, color2, nv_color.r);
      gl_FragColor  = vec4(c, 1.0);
  }
  `;
</script>
prisoner849
  • 16,894
  • 4
  • 34
  • 68
  • exactly what i was looking for. but i didn't get the js part in the html section. What does the `\`` do? And is there a specific reason why this code is in the html part? – d4rty Feb 10 '18 at 14:38
  • @d4rty '`' is for multiline strings in modern browsers, thus you don't need to use array of strings for shaders. Kind of simplification of life :) – prisoner849 Feb 10 '18 at 15:13