<div id="container">
  <div id="control-panel">
    <h3>lights</h3>
    <div class="input">
      <label>ambientLight</label>
      <input id="ambientLight" type="range" min="0" max="1" step="0.1" value="0.4"></input>
      <span id="ambientLight-value"></span>
    </div>
    <div class="input">
      <label>directionalLight</label>
      <input id="directionalLight" type="range" min="0" max="1" step="0.1" value="1"></input>
      <span id="directionalLight-value"></span>
    </div>
    <div class="input">
      <label style="color: #f80">pointLight1</label>
      <input id="pointLight1" type="range" min="0" max="1" step="0.1" value="1"></input>
      <span id="pointLight1-value"></span>
    </div>
    <div class="input">
      <label style="color: #08f">pointLight2</label>
      <input id="pointLight2" type="range" min="0" max="1" step="0.1" value="0"></input>
      <span id="pointLight2-value"></span>
    </div>
    <div class="input">
      <label>cameraLight</label>
      <input id="cameraLight" type="range" min="0" max="1" step="0.1" value="0"></input>
      <span id="cameraLight-value"></span>
    </div>

    <h3>material</h3>
    <div class="input">
      <label>ambient</label>
      <input id="ambient" type="range" min="0" max="1" step="0.1" value="0.5"></input>
      <span id="ambient-value"></span>
    </div>
    <div class="input">
      <label>diffuse</label>
      <input id="diffuse" type="range" min="0" max="1" step="0.1" value="0.5"></input>
      <span id="diffuse-value"></span>
    </div>
    <div class="input">
      <label>shininess</label>
      <input id="shininess" type="range" min="0" max="1000" step="1" value="100"></input>
      <span id="shininess-value"></span>
    </div>
    <div>
      <label>specularColor</label>
      <div class="input">
        <label>R</label>
        <input id="specularR" type="range" min="0" max="255" step="1" value="255"></input>
        <span id="specularR-value"></span>
      </div>
      <div class="input">
        <label>G</label>
        <input id="specularG" type="range" min="0" max="255" step="1" value="255"></input>
        <span id="specularG-value"></span>
      </div>
      <div class="input">
        <label>B</label>
        <input id="specularB" type="range" min="0" max="255" step="1" value="255"></input>
        <span id="specularB-value"></span>
      </div>
    </div>
  </div>
  <div id="deckgl"></div>
</div>
#container {
  position: fixed;
  width: 100vw;
  height: 100vh;
  top: 0;
  left: 0;
  background: #111;
  display: flex;
}

#deckgl {
  flex-grow: 1;
}

#control-panel {
  font-family: Helvetica, Arial, sans-serif;
  background: #fff;
  padding: 20px;
  z-index: 1;
  line-height: 1.6;
  overflow-y: auto;
}
#control-panel div {
  padding-left: 10px;
}

.input {
  display: flex;
}
.input label {
  flex-grow: 1;
}
.input input {
  width: 140px;
  margin: 0 8px;
}
.input span {
  width: 40px;
}
const INPUTS = Array.from(document.querySelectorAll('input'));

const sphereLayoutData = [
  {position: [-25, 0, 0]},
  {position: [25, 0, 0]},
];
const sphereMesh = new luma.SphereGeometry({
  radius: 20,
  nlat: 100,
  nlong: 100
});
const ambientLight = new deck.AmbientLight({
  color: [255, 255, 255],
  intensity: 1
});
const pointLight1 = new deck.PointLight({
  color: [255, 128, 0],
  intensity: 1,
  position: [0, 0, 30]
});
const pointLight2 = new deck.PointLight({
  color: [0, 128, 255],
  intensity: 1,
  position: [50, 50, 50]
});
const cameraLight = new deck._CameraLight({
  color: [255, 255, 255],
  intensity: 0.2
});
const directionalLight = new deck.DirectionalLight({
  color: [255, 255, 255],
  direction: [0, 0, -1],
  intensity: 1
});
const sphereMaterial = {};

const deckgl = new deck.DeckGL({
  container: document.getElementById('deckgl'),
  views: [new deck.OrbitView({fov: 50})],
  initialViewState: {target: [0, 0, 0], rotationX: 0, zoom: 2},
  controller: true,
  effects: [
    new deck.LightingEffect({ambientLight, pointLight1, pointLight2, cameraLight, directionalLight})
  ],
  layers: [
    new deck.PointCloudLayer({
      id: 'point-lights',
      data: [pointLight1, pointLight2],
      coordinateSystem: deck.COORDINATE_SYSTEM.IDENTITY,
      getPosition: d => d.position,
      getColor: d => d.color,
      pointSize: 5,
      material: null
    }),
    new deck.SimpleMeshLayer({
      id: 'spheres',
      coordinateSystem: deck.COORDINATE_SYSTEM.IDENTITY,
      opacity: 1,
      data: sphereLayoutData,
      mesh: sphereMesh,
      getPosition: d => d.position,
      getColor: [128, 128, 128],
      material: sphereMaterial
    })
  ]
});

redraw();

INPUTS.forEach(el => {
  el.oninput = redraw;
});

function redraw() {
  const settings = {};
  INPUTS.forEach(el => {
    const name = el.id;
    const value = +el.value;
    settings[name] = value;
    document.getElementById(name + '-value').innerHTML = value;
  });
  
  ambientLight.intensity = settings.ambientLight;
  directionalLight.intensity = settings.directionalLight;
  cameraLight.intensity = settings.cameraLight;
  pointLight1.intensity = settings.pointLight1;
  pointLight2.intensity = settings.pointLight2;
  
  sphereMaterial.ambient = settings.ambient;
  sphereMaterial.diffuse = settings.diffuse;
  sphereMaterial.shininess = settings.shininess;
  sphereMaterial.specularColor = [settings.specularR, settings.specularG, settings.specularB];
  
  deckgl.redraw(true);
}

External CSS

  1. https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css

External JavaScript

  1. https://unpkg.com/deck.gl@latest/dist.min.js