1

based on previous questions: Outline object (normal scale + stencil mask) three.js

I am trying to make a material shader for threejs to render only the contour and not both with the object. Should this be the right reference or is there a more straighforward way to do it?

1
  • 2
    There is already an official example for an outline post-processing effect (threejs.org/examples/#webgl_postprocessing_outline). Maybe you can use/adjust it instead of creating a custom one from scratch. Commented Apr 4, 2018 at 19:54

1 Answer 1

2

At the moment, the most straightforward solution I could find is from: https://stemkoski.github.io/Three.js/Outline.html with a slightly scaled marching cube using side: THREE.BackSide param in its material.


Adding the code referenced above:

<!doctype html>
<html lang="en">

<head>
  <title>Outline effect (Three.js)</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  <link rel=stylesheet href="css/base.css" />
</head>

<body>

  <script src="js/Three.js"></script>
  <script src="js/Detector.js"></script>
  <script src="js/Stats.js"></script>
  <script src="js/OrbitControls.js"></script>
  <script src="js/THREEx.KeyboardState.js"></script>
  <script src="js/THREEx.FullScreen.js"></script>
  <script src="js/THREEx.WindowResize.js"></script>

  <!-- jQuery code to display an information button and box when clicked. -->
  <script src="js/jquery-1.9.1.js"></script>
  <script src="js/jquery-ui.js"></script>
  <link rel=stylesheet href="css/jquery-ui.css" />
  <link rel=stylesheet href="css/info.css" />
  <script src="js/info.js"></script>
  <div id="infoButton"></div>
  <div id="infoBox" title="Demo Information">
    This three.js demo is part of a collection at
    <a href="http://stemkoski.github.io/Three.js/">http://stemkoski.github.io/Three.js/</a>
  </div>
  <!-- ------------------------------------------------------------ -->

  <div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
  <script>
    /*
    Three.js "tutorials by example"
    Author: Lee Stemkoski
    Date: July 2013 (three.js v59dev)
 */

    // MAIN

    // standard global variables
    var container, scene, camera, renderer, controls, stats;
    var keyboard = new THREEx.KeyboardState();
    var clock = new THREE.Clock();
    // custom global variables
    var cube;

    init();
    animate();

    // FUNCTIONS        
    function init() {
      // SCENE
      scene = new THREE.Scene();
      // CAMERA
      var SCREEN_WIDTH = window.innerWidth,
        SCREEN_HEIGHT = window.innerHeight;
      var VIEW_ANGLE = 45,
        ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT,
        NEAR = 0.1,
        FAR = 20000;
      camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
      scene.add(camera);
      camera.position.set(0, 150, 400);
      camera.lookAt(scene.position);
      // RENDERER
      if (Detector.webgl)
        renderer = new THREE.WebGLRenderer({
          antialias: true
        });
      else
        renderer = new THREE.CanvasRenderer();
      renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
      container = document.getElementById('ThreeJS');
      container.appendChild(renderer.domElement);
      // EVENTS
      THREEx.WindowResize(renderer, camera);
      THREEx.FullScreen.bindKey({
        charCode: 'm'.charCodeAt(0)
      });
      // CONTROLS
      controls = new THREE.OrbitControls(camera, renderer.domElement);
      // STATS
      stats = new Stats();
      stats.domElement.style.position = 'absolute';
      stats.domElement.style.bottom = '0px';
      stats.domElement.style.zIndex = 100;
      container.appendChild(stats.domElement);
      // LIGHT
      var light = new THREE.PointLight(0xffffff);
      light.position.set(0, 150, 100);
      scene.add(light);
      // FLOOR
      var floorTexture = new THREE.ImageUtils.loadTexture('images/checkerboard.jpg');
      floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
      floorTexture.repeat.set(10, 10);
      var floorMaterial = new THREE.MeshBasicMaterial({
        map: floorTexture,
        side: THREE.DoubleSide
      });
      var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
      var floor = new THREE.Mesh(floorGeometry, floorMaterial);
      floor.position.y = -0.5;
      floor.rotation.x = Math.PI / 2;
      scene.add(floor);
      // SKYBOX/FOG
      var skyBoxGeometry = new THREE.CubeGeometry(10000, 10000, 10000);
      var skyBoxMaterial = new THREE.MeshBasicMaterial({
        color: 0x9999ff,
        side: THREE.BackSide
      });
      var skyBox = new THREE.Mesh(skyBoxGeometry, skyBoxMaterial);
      scene.add(skyBox);

      ////////////
      // CUSTOM //
      ////////////

      var material = new THREE.MeshNormalMaterial();

      var sphereGeometry = new THREE.SphereGeometry(50, 32, 16);
      var sphere = new THREE.Mesh(sphereGeometry, material);
      sphere.position.set(-60, 55, 0);
      scene.add(sphere);

      var outlineMaterial1 = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        side: THREE.BackSide
      });
      var outlineMesh1 = new THREE.Mesh(sphereGeometry, outlineMaterial1);
      outlineMesh1.position = sphere.position;
      outlineMesh1.scale.multiplyScalar(1.05);
      scene.add(outlineMesh1);

      var cubeGeometry = new THREE.CubeGeometry(80, 80, 80);
      var cube = new THREE.Mesh(cubeGeometry, material);
      cube.position.set(60, 60, 0);
      scene.add(cube);

      var outlineMaterial2 = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        side: THREE.BackSide
      });
      var outlineMesh2 = new THREE.Mesh(cubeGeometry, outlineMaterial2);
      outlineMesh2.position = cube.position;
      outlineMesh2.scale.multiplyScalar(1.05);
      scene.add(outlineMesh2);

    }

    function animate() {
      requestAnimationFrame(animate);
      render();
      update();
    }

    function update() {
      if (keyboard.pressed("z")) {
        // do something
      }

      controls.update();
      stats.update();
    }

    function render() {
      renderer.render(scene, camera);
    }
  </script>

</body>

</html>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.