В три. js как сделать свет на сфере острым? - PullRequest
1 голос
/ 23 апреля 2020

У меня есть простые три. 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>

Ответы [ 2 ]

3 голосов
/ 23 апреля 2020

Одним из способов достижения желаемого эффекта является использование теней. Следовательно, попробуйте MeshToonMaterial . Вы также можете определить градиент карты , который определяет отдельные освещенные области материала.

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>
0 голосов
/ 23 апреля 2020

Вы можете установить material.shininess. Смотрите это

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>

Обратите внимание, что представленная выше градиентная карта имеет текстуру 2x1 пикселя, поэтому срез будет на 50% между обращением к свету и не обращением к нему. Чтобы переместить обрезку, увеличьте Градиент. Например, текстура 5x1 пикселей с black, black, white, white, white будет 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 цветов / делений, поместите более 2 цветов в градиентную карту

...