【问题标题】:In three.js how to make light on sphere sharp?在three.js中如何使球体锐利?
【发布时间】:2020-04-24 15:33:13
【问题描述】:

我有一个简单的three.js 场景,带有球体和定向光。在球体上,您可以看到它逐渐变暗。如何更快地从明暗过渡。如何让光线“更锐利”?

var scene, camera, renderer, controls, sphere, geometry, material, light;

scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 3;
camera.position.z = 6;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff, 1);
document.body.appendChild(renderer.domElement);

geometry = new THREE.SphereGeometry(1, 32, 32);
material = new THREE.MeshPhongMaterial({
  color: 0x777777
});
sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);

light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 10, 10);
scene.add(light);

renderer.render(scene, camera);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"></script>

【问题讨论】:

    标签: javascript three.js webgl


    【解决方案1】:

    实现预期效果的一种方法是通过卡通着色。因此,试试MeshToonMaterial。您还可以定义 gradientMap 来定义材质的不同照明区域。

    var scene, camera, renderer, controls, sphere, geometry, material, light;
    
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.x = 3;
    camera.position.z = 6;
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor(0xffffff, 1);
    document.body.appendChild(renderer.domElement);
    
    geometry = new THREE.SphereGeometry(1, 32, 32);
    material = new THREE.MeshToonMaterial({
      color: 0x777777
    });
    sphere = new THREE.Mesh(geometry, material);
    scene.add(sphere);
    
    light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(0, 10, 10);
    scene.add(light);
    
    renderer.render(scene, camera);
    <script src="https://cdn.jsdelivr.net/npm/three@0.115/build/three.js"></script>

    【讨论】:

      【解决方案2】:

      您可以设置material.shininessSee this

      var scene, camera, renderer, controls, sphere, geometry, material, light;
      
      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.x = 1;
      camera.position.z = 2;
      renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setClearColor(0xffffff, 1);
      document.body.appendChild(renderer.domElement);
      
      geometry = new THREE.SphereGeometry(1, 32, 32);
      material = new THREE.MeshPhongMaterial({
        color: 0x777777,
        shininess: 400,
      });
      sphere = new THREE.Mesh(geometry, material);
      scene.add(sphere);
      
      light = new THREE.DirectionalLight(0xffffff, 1);
      light.position.set(0, 10, 10);
      scene.add(light);
      
      renderer.render(scene, camera);
      <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"></script>

      即使使用 MeshToonMaterial,如果您不想要高光,也需要将 shininess 设置为 0

      var scene, camera, renderer, controls, sphere, geometry, material, light;
      
      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.x = 1;
      camera.position.z = 2;
      renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setClearColor(0xffffff, 1);
      document.body.appendChild(renderer.domElement);
      
      geometry = new THREE.SphereGeometry(1, 32, 32);
      material = new THREE.MeshToonMaterial({
        color: 0x777777,
        shininess: 0,
      
      });
      sphere = new THREE.Mesh(geometry, material);
      scene.add(sphere);
      
      light = new THREE.DirectionalLight(0xffffff, 1);
      light.position.set(0, 10, 10);
      scene.add(light);
      
      renderer.render(scene, camera);
      <script src="https://cdn.jsdelivr.net/npm/three@0.115/build/three.js"></script>

      此外,除非您使用gradientMap,否则相对光量是硬编码的

      var scene, camera, renderer, controls, sphere, geometry, material, light;
      
      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.x = 0;
      camera.position.z = 2;
      renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setClearColor(0xffffff, 1);
      document.body.appendChild(renderer.domElement);
      
      geometry = new THREE.SphereGeometry(1, 32, 32);
      material = new THREE.MeshToonMaterial({
        color: 'red',
        shininess: 0,
        gradientMap: new THREE.DataTexture(
          new Uint8Array([
              0,   // black (color away from light multiplied by color of material)
            255,   // white (color toward light multiplied by material
          ]),
          2, // width of texture
          1, // height of texture,
          THREE.LuminanceFormat,  // format of texture
        ),
      });
      sphere = new THREE.Mesh(geometry, material);
      scene.add(sphere);
      
      light = new THREE.DirectionalLight(0xffffff, 1);
      light.position.set(50, 50, 30);
      scene.add(light);
      
      renderer.render(scene, camera);
      <script src="https://cdn.jsdelivr.net/npm/three@0.115/build/three.js"></script>

      请注意,上面的 gradientMap 是一个 2x1 像素的纹理,因此在面向灯光和不面向灯光之间的截止值为 50%。要移动截止点,请使 gradientMap 更大。例如,black, black, white, white, white 的 5x1 像素纹理将是 40% 黑色,60% 白色

      var scene, camera, renderer, controls, sphere, geometry, material, light;
      
      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.x = 0;
      camera.position.z = 2;
      renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setClearColor(0xffffff, 1);
      document.body.appendChild(renderer.domElement);
      
      geometry = new THREE.SphereGeometry(1, 32, 32);
      material = new THREE.MeshToonMaterial({
        color: 'red',
        shininess: 0,
        gradientMap: new THREE.DataTexture(
          new Uint8Array([
              0,   // black (color away from light multiplied by color of material)
              0,
            255,   // white (color toward light multiplied by material
            255, 
            255,
          ]),
          5, // width of texture
          1, // height of texture,
          THREE.LuminanceFormat,  // format of texture
        ),
      });
      sphere = new THREE.Mesh(geometry, material);
      scene.add(sphere);
      
      light = new THREE.DirectionalLight(0xffffff, 1);
      light.position.set(50, 50, 30);
      scene.add(light);
      
      renderer.render(scene, camera);
      <script src="https://cdn.jsdelivr.net/npm/three@0.115/build/three.js"></script>

      如果您想明确设置 2 种颜色,则使 gradientMap 具有颜色并将材质颜色设置为白色

      var scene, camera, renderer, controls, sphere, geometry, material, light;
      
      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.x = 0;
      camera.position.z = 2;
      renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setClearColor(0xffffff, 1);
      document.body.appendChild(renderer.domElement);
      
      geometry = new THREE.SphereGeometry(1, 32, 32);
      material = new THREE.MeshToonMaterial({
        color: 'white',
        shininess: 0,
        gradientMap: new THREE.DataTexture(
          new Uint8Array([
              255, 0, 255,   // purple (color away from light multiplied by color of material)
              0, 255, 255,   // cyan (color toward light multiplied by material
          ]),
          2, // width of texture
          1, // height of texture,
          THREE.RGBFormat,  // format of texture
        ),
      });
      sphere = new THREE.Mesh(geometry, material);
      scene.add(sphere);
      
      light = new THREE.DirectionalLight(0xffffff, 1);
      light.position.set(50, 50, 30);
      scene.add(light);
      
      renderer.render(scene, camera);
      <script src="https://cdn.jsdelivr.net/npm/three@0.115/build/three.js"></script>

      如果您想要超过 2 种颜色/分区,则在 gradientMap 中放置超过 2 种颜色

      【讨论】:

      • 我不想要镜面反射,我想要将球体分成两半,一亮一暗。
      • Mugen87 的回答涵盖了这一点,我的回答中的链接也是如此。请注意,如果您只需要两种颜色,则需要使用MeshToonMaterial,将material.shininess 设置为0,如果您希望能够设置颜色和/或截止位置,则需要提供gradientMap /跨度>
      猜你喜欢
      • 1970-01-01
      • 2012-04-21
      • 2011-10-18
      • 2019-11-12
      • 1970-01-01
      • 2014-06-17
      • 2013-06-22
      • 2015-09-22
      • 1970-01-01
      相关资源
      最近更新 更多