带有Three.js的WebGL –第3课

WebGL With Three.js - Lesson 3
WebGL With Three.js - Lesson 3

WebGL With Three.js – Lesson 3 Most programmers who are just starting to comprehend the basics of working with 3D (in webgl), usually have difficulties in understanding three-dimensional space. Because we have one extra dimension (volume) compared with what you are used to. Also you may have difficulty in understanding how the different light works, or even how axis are located in space. Today I will help you to deal with these issues. Three.js has all the necessary means to for this – Helpers. In today’s examples, I have prepared you for working demonstration of all existing helpers: ArrowHelper, AxisHelper, BoundingBoxHelper, CameraHelper, DirectionalLightHelper, GridHelper, HemisphereLightHelper, PointLightHelper, SpotLightHelper. All of them will help you understand the insides of WebGL.

带有Three.js的WebGL –第3课大多数刚开始理解3D工作原理 (在webgl中)的程序员通常在理解三维空间方面遇到困难。 因为与您习惯的相比,我们有一个额外的维度(体积)。 另外,您可能很难理解不同的光源如何工作,甚至轴如何在空间中定位。 今天,我将帮助您处理这些问题。 Three.js为此提供了所有必要的手段-Helpers。 在今天的示例中,我为您准备了所有现有助手的工作演示:ArrowHelper,AxisHelper,BoundingBoxHelper,CameraHelper,DirectionalLightHelper,GridHelper,HemisphereLightHelper,PointLightHelper,SpotLightHelper。 所有这些都将帮助您了解WebGL的内部。

现场演示
现场演示2

HTML (HTML)

This section has not changed, nothing has been added:

本节未更改,未添加任何内容:


<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <meta name="author" content="Script Tutorials" />
        <title>WebGL With Three.js - Lesson 3 | Script Tutorials</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
        <link href="css/main.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <script src="js/three.min.js"></script>
        <script src="js/THREEx.WindowResize.js"></script>
        <script src="js/OrbitControls.js"></script>
        <script src="js/stats.min.js"></script>
        <script src="js/script.js"></script>
    </body>
</html>

<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <meta name="author" content="Script Tutorials" />
        <title>WebGL With Three.js - Lesson 3 | Script Tutorials</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
        <link href="css/main.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <script src="js/three.min.js"></script>
        <script src="js/THREEx.WindowResize.js"></script>
        <script src="js/OrbitControls.js"></script>
        <script src="js/stats.min.js"></script>
        <script src="js/script.js"></script>
    </body>
</html>

Java脚本 (Javascript)

For a start, let’s create some simple scene that includes the following elements: camera, direct light, the ground and two spheres.:

首先,让我们创建一些简单的场景,其中包括以下元素:相机,直射光,地面和两个球体:


var dLight, bboxHelper, dlightHelper;
// load texture
var texture = THREE.ImageUtils.loadTexture('texture.png');
texture.repeat.set(10, 10);
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.anisotropy = 16;
texture.needsUpdate = true;
var textureBump = THREE.ImageUtils.loadTexture('bump.png');
textureBump.repeat.set(10, 10);
textureBump.wrapS = textureBump.wrapT = THREE.RepeatWrapping;
textureBump.anisotropy = 16;
textureBump.needsUpdate = true;
var lesson3 = {
    scene: null,
    camera: null,
    renderer: null,
    container: null,
    controls: null,
    clock: null,
    stats: null,
    init: function() { // Initialization
        // create main scene
        this.scene = new THREE.Scene();
        var SCREEN_WIDTH = window.innerWidth,
            SCREEN_HEIGHT = window.innerHeight;
        // prepare camera
        var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 1, FAR = 10000;
        this.camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
        this.scene.add(this.camera);
        this.camera.position.set(-1600, 600, 1200);
        this.camera.lookAt(new THREE.Vector3(0,0,0));
        // prepare renderer
        this.renderer = new THREE.WebGLRenderer({antialias:true, alpha: false});
        this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
        this.renderer.setClearColor(0xffffff);
        this.renderer.shadowMapEnabled = true;
        this.renderer.shadowMapSoft = true;
        // prepare container
        this.container = document.createElement('div');
        document.body.appendChild(this.container);
        this.container.appendChild(this.renderer.domElement);
        // events
        THREEx.WindowResize(this.renderer, this.camera);
        // prepare controls (OrbitControls)
        this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
        this.controls.target = new THREE.Vector3(0, 0, 0);
        // prepare clock
        this.clock = new THREE.Clock();
        // prepare stats
        this.stats = new Stats();
        this.stats.domElement.style.position = 'absolute';
        this.stats.domElement.style.bottom = '0px';
        this.stats.domElement.style.zIndex = 10;
        this.container.appendChild( this.stats.domElement );
        // add directional light
        dLight = new THREE.DirectionalLight(0xffffff);
        dLight.position.set(0, 400, 0);
        dLight.castShadow = true;
        // dLight.shadowCameraVisible = true;
        dLight.shadowMapWidth = dLight.shadowMapHeight = 1000;
        this.scene.add(dLight);
        // add simple ground
        var groundGeometry = new THREE.PlaneGeometry(1200, 1200, 1, 1);
        ground = new THREE.Mesh(groundGeometry, new THREE.MeshLambertMaterial({
            color: 0x9669FE
        }));
        ground.position.y = -20;
        ground.rotation.x = - Math.PI / 2;
        ground.receiveShadow = true;
        this.scene.add(ground);
        // create a new group (Object3D)
        var group = new THREE.Object3D();
        // add two spheres
        var sphere  = this.drawSphere(-100, 150, new THREE.MeshPhongMaterial({ map: texture, bumpMap: textureBump, color: 0x00ff00, specular: 0xff2200, emissive: 0x004000 }));
        var sphere2 = this.drawSphere( 100, 150, new THREE.MeshPhongMaterial({ map: texture, bumpMap: textureBump, color: 0x00ff00, specular: 0xff2200, shininess: 3 }));
        // and add them into the group
        group.add(sphere);
        group.add(sphere2);
        this.scene.add(group);
    },
    drawSphere: function(x, z, material) {
        var sphere = new THREE.Mesh(new THREE.SphereGeometry(70, 70, 20), material);
        sphere.rotation.x = sphere.rotation.z = Math.PI * Math.random();
        sphere.position.x = x;
        sphere.position.y = 100;
        sphere.position.z = z;
        sphere.castShadow = sphere.receiveShadow = true;
        return sphere;
    }
};
// Animate the scene
function animate() {
    requestAnimationFrame(animate);
    render();
    update();
}
// Update controls and stats
function update() {
    bboxHelper.update();
    dlightHelper.update();
    lesson3.controls.update(lesson3.clock.getDelta());
    lesson3.stats.update();
    // smoothly move the dLight
    var timer = Date.now() * 0.000025;
    dLight.position.x = Math.sin(timer * 5) * 300;
    dLight.position.z = Math.cos(timer * 5) * 300;
}
// Render the scene
function render() {
    if (lesson3.renderer) {
        lesson3.renderer.render(lesson3.scene, lesson3.camera);
    }
}
// Initialize lesson on page load
function initializeLesson() {
    lesson3.init();
    animate();
}
if (window.addEventListener)
    window.addEventListener('load', initializeLesson, false);
else if (window.attachEvent)
    window.attachEvent('onload', initializeLesson);
else window.onload = initializeLesson;

var dLight, bboxHelper, dlightHelper;
// load texture
var texture = THREE.ImageUtils.loadTexture('texture.png');
texture.repeat.set(10, 10);
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.anisotropy = 16;
texture.needsUpdate = true;
var textureBump = THREE.ImageUtils.loadTexture('bump.png');
textureBump.repeat.set(10, 10);
textureBump.wrapS = textureBump.wrapT = THREE.RepeatWrapping;
textureBump.anisotropy = 16;
textureBump.needsUpdate = true;
var lesson3 = {
    scene: null,
    camera: null,
    renderer: null,
    container: null,
    controls: null,
    clock: null,
    stats: null,
    init: function() { // Initialization
        // create main scene
        this.scene = new THREE.Scene();
        var SCREEN_WIDTH = window.innerWidth,
            SCREEN_HEIGHT = window.innerHeight;
        // prepare camera
        var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 1, FAR = 10000;
        this.camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
        this.scene.add(this.camera);
        this.camera.position.set(-1600, 600, 1200);
        this.camera.lookAt(new THREE.Vector3(0,0,0));
        // prepare renderer
        this.renderer = new THREE.WebGLRenderer({antialias:true, alpha: false});
        this.renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
        this.renderer.setClearColor(0xffffff);
        this.renderer.shadowMapEnabled = true;
        this.renderer.shadowMapSoft = true;
        // prepare container
        this.container = document.createElement('div');
        document.body.appendChild(this.container);
        this.container.appendChild(this.renderer.domElement);
        // events
        THREEx.WindowResize(this.renderer, this.camera);
        // prepare controls (OrbitControls)
        this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
        this.controls.target = new THREE.Vector3(0, 0, 0);
        // prepare clock
        this.clock = new THREE.Clock();
        // prepare stats
        this.stats = new Stats();
        this.stats.domElement.style.position = 'absolute';
        this.stats.domElement.style.bottom = '0px';
        this.stats.domElement.style.zIndex = 10;
        this.container.appendChild( this.stats.domElement );
        // add directional light
        dLight = new THREE.DirectionalLight(0xffffff);
        dLight.position.set(0, 400, 0);
        dLight.castShadow = true;
        // dLight.shadowCameraVisible = true;
        dLight.shadowMapWidth = dLight.shadowMapHeight = 1000;
        this.scene.add(dLight);
        // add simple ground
        var groundGeometry = new THREE.PlaneGeometry(1200, 1200, 1, 1);
        ground = new THREE.Mesh(groundGeometry, new THREE.MeshLambertMaterial({
            color: 0x9669FE
        }));
        ground.position.y = -20;
        ground.rotation.x = - Math.PI / 2;
        ground.receiveShadow = true;
        this.scene.add(ground);
        // create a new group (Object3D)
        var group = new THREE.Object3D();
        // add two spheres
        var sphere  = this.drawSphere(-100, 150, new THREE.MeshPhongMaterial({ map: texture, bumpMap: textureBump, color: 0x00ff00, specular: 0xff2200, emissive: 0x004000 }));
        var sphere2 = this.drawSphere( 100, 150, new THREE.MeshPhongMaterial({ map: texture, bumpMap: textureBump, color: 0x00ff00, specular: 0xff2200, shininess: 3 }));
        // and add them into the group
        group.add(sphere);
        group.add(sphere2);
        this.scene.add(group);
    },
    drawSphere: function(x, z, material) {
        var sphere = new THREE.Mesh(new THREE.SphereGeometry(70, 70, 20), material);
        sphere.rotation.x = sphere.rotation.z = Math.PI * Math.random();
        sphere.position.x = x;
        sphere.position.y = 100;
        sphere.position.z = z;
        sphere.castShadow = sphere.receiveShadow = true;
        return sphere;
    }
};
// Animate the scene
function animate() {
    requestAnimationFrame(animate);
    render();
    update();
}
// Update controls and stats
function update() {
    bboxHelper.update();
    dlightHelper.update();
    lesson3.controls.update(lesson3.clock.getDelta());
    lesson3.stats.update();
    // smoothly move the dLight
    var timer = Date.now() * 0.000025;
    dLight.position.x = Math.sin(timer * 5) * 300;
    dLight.position.z = Math.cos(timer * 5) * 300;
}
// Render the scene
function render() {
    if (lesson3.renderer) {
        lesson3.renderer.render(lesson3.scene, lesson3.camera);
    }
}
// Initialize lesson on page load
function initializeLesson() {
    lesson3.init();
    animate();
}
if (window.addEventListener)
    window.addEventListener('load', initializeLesson, false);
else if (window.attachEvent)
    window.attachEvent('onload', initializeLesson);
else window.onload = initializeLesson;

Please pay attention that two spheres were added into the group (which is ordinary Object3D object). Now, we can start the overview of the helpers.

请注意,两个球体已添加到组中(这是普通的Object3D对象)。 现在,我们可以开始概述助手。

ArrowHelper (ArrowHelper)

It draws a 3D arrow (starting in origin in the direction dir for a certain length) in space. This helps to understand the direction of a vector in space. To add this helper, use the following code:

它在空间中绘制3D箭头(从dir的原点开始一定的长度)。 这有助于了解向量在空间中的方向。 要添加此帮助程序,请使用以下代码:


  // 1. ArrowHelper
  var directionV3 = new THREE.Vector3(1, 0, 1);
  var originV3 = new THREE.Vector3(0, 200, 0);
  var arrowHelper = new THREE.ArrowHelper(directionV3, originV3, 100, 0xff0000, 20, 10); // 100 is length, 20 and 10 are head length and width
  this.scene.add(arrowHelper);

  // 1. ArrowHelper
  var directionV3 = new THREE.Vector3(1, 0, 1);
  var originV3 = new THREE.Vector3(0, 200, 0);
  var arrowHelper = new THREE.ArrowHelper(directionV3, originV3, 100, 0xff0000, 20, 10); // 100 is length, 20 and 10 are head length and width
  this.scene.add(arrowHelper);

AxisHelper (AxisHelper)

It draws an axis object to visualize the the 3 axis in a simple way. The X axis is red. The Y axis is green. The Z axis is blue. This helps to understand the direction of all three axis in space. To add this helper, use the following code:

它绘制一个轴对象以一种简单的方式可视化3轴。 X轴为红色。 Y轴为绿色。 Z轴为蓝色。 这有助于了解空间中所有三个轴的方向。 要添加此帮助程序,请使用以下代码:


  // 2. AxisHelper
  var axisHelper = new THREE.AxisHelper(800); // 500 is size
  this.scene.add(axisHelper);

  // 2. AxisHelper
  var axisHelper = new THREE.AxisHelper(800); // 500 is size
  this.scene.add(axisHelper);

BoundingBoxHelper (BoundingBoxHelper)

It draws a line object to the boundingbox of any object (Object3D) to show the world-axis-aligned bounding box for this object. Remember what we combined the two spheres in the single group object? To add this helper, use the following code:

它将线形对象绘制到任何对象(Object3D)的边界框,以显示该对象与世界轴对齐的边界框。 还记得我们在单个组对象中将两个领域结合在一起的情况吗? 要添加此帮助程序,请使用以下代码:


  // 3. BoundingBoxHelper
  bboxHelper = new THREE.BoundingBoxHelper(group, 0x999999);
  this.scene.add(bboxHelper);

  // 3. BoundingBoxHelper
  bboxHelper = new THREE.BoundingBoxHelper(group, 0x999999);
  this.scene.add(bboxHelper);

相机助手 (CameraHelper)

It draws a specific Object3D object (it looks like pyramid) with line geometry, that helps visualizing what a specified camera contains in its frustum. To add this helper, use the following code:

它绘制具有线几何的特定Object3D对象(看起来像金字塔),有助于可视化指定摄像机的视锥中包含的内容。 要添加此帮助程序,请使用以下代码:


  // 4. CameraHelper
  var cameraParObj = new THREE.Object3D();
  cameraParObj.position.y = 200;
  cameraParObj.position.z = 700;
  this.scene.add(cameraParObj);
  perspectiveCamera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.01, 1500);
  cameraParObj.add(perspectiveCamera);
  var cameraHelper = new THREE.CameraHelper(perspectiveCamera);
  this.scene.add(cameraHelper);

  // 4. CameraHelper
  var cameraParObj = new THREE.Object3D();
  cameraParObj.position.y = 200;
  cameraParObj.position.z = 700;
  this.scene.add(cameraParObj);
  perspectiveCamera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.01, 1500);
  cameraParObj.add(perspectiveCamera);
  var cameraHelper = new THREE.CameraHelper(perspectiveCamera);
  this.scene.add(cameraHelper);

DirectionalLightHelper (DirectionalLightHelper)

It draws a line object to show the direction of a directional light. We will gradually move our source of light for you to see clearly this helper. To add this helper, use the following code:

它绘制线对象以显示定向光的方向。 我们将逐步移动光源,以使您清楚地看到该帮助器。 要添加此帮助程序,请使用以下代码:


  // 5. DirectionalLightHelper
  dlightHelper = new THREE.DirectionalLightHelper(dLight, 50); // 50 is helper size
  this.scene.add(dlightHelper);

  // 5. DirectionalLightHelper
  dlightHelper = new THREE.DirectionalLightHelper(dLight, 50); // 50 is helper size
  this.scene.add(dlightHelper);

GridHelper (GridHelper)

To see the rest of the helpers, we created the second demo. The next is GridHelper, this helper draws a two-dimensional grid of lines. To add this helper, use the following code:

为了查看其余的助手,我们创建了第二个演示。 下一个是GridHelper,此帮助程序绘制二维线形网格。 要添加此帮助程序,请使用以下代码:


  var gridHelper = new THREE.GridHelper(500, 40); // 500 is grid size, 20 is grid step
  gridHelper.position = new THREE.Vector3(0, 0, 0);
  gridHelper.rotation = new THREE.Euler(0, 0, 0);
  this.scene.add(gridHelper);
  var gridHelper2 = gridHelper.clone();
  gridHelper2.rotation = new THREE.Euler(Math.PI / 2, 0, 0);
  this.scene.add(gridHelper2);
  var gridHelper3 = gridHelper.clone();
  gridHelper3.rotation = new THREE.Euler(Math.PI / 2, 0, Math.PI / 2);
  this.scene.add(gridHelper3);

  var gridHelper = new THREE.GridHelper(500, 40); // 500 is grid size, 20 is grid step
  gridHelper.position = new THREE.Vector3(0, 0, 0);
  gridHelper.rotation = new THREE.Euler(0, 0, 0);
  this.scene.add(gridHelper);
  var gridHelper2 = gridHelper.clone();
  gridHelper2.rotation = new THREE.Euler(Math.PI / 2, 0, 0);
  this.scene.add(gridHelper2);
  var gridHelper3 = gridHelper.clone();
  gridHelper3.rotation = new THREE.Euler(Math.PI / 2, 0, Math.PI / 2);
  this.scene.add(gridHelper3);

Please note, that we created three two-dimensional grid (for all three axis).

请注意,我们创建了三个二维网格(用于所有三个轴)。

半球光助手 (HemisphereLightHelper)

The rest three helpers are for lights, the HemisphereLightHelper is for HemisphereLight object. We had to turn off our directional light and enable the hemisphere light. To add this helper, use the following code:

其余三个助手用于灯光,HemisphereLightHelper用于HemisphereLight对象。 我们必须关闭定向灯并启用半球灯。 要添加此帮助程序,请使用以下代码:


  // add hemisphere light
  var hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.4);
  hemiLight.color.setHSL(0.6, 1, 0.6);
  hemiLight.groundColor.setHSL(0.095, 1, 0.75);
  hemiLight.position.set(-200, 400, -200);
  this.scene.add(hemiLight);
  var hlightHelper = new THREE.HemisphereLightHelper(hemiLight, 50, 300); // 50 is sphere size, 300 is arrow length
  this.scene.add(hlightHelper);

  // add hemisphere light
  var hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.4);
  hemiLight.color.setHSL(0.6, 1, 0.6);
  hemiLight.groundColor.setHSL(0.095, 1, 0.75);
  hemiLight.position.set(-200, 400, -200);
  this.scene.add(hemiLight);
  var hlightHelper = new THREE.HemisphereLightHelper(hemiLight, 50, 300); // 50 is sphere size, 300 is arrow length
  this.scene.add(hlightHelper);

PointLightHelper (PointLightHelper)

Similar to the previous, the PointLightHelper is for PointLight object. To add this helper, use the following code:

与前面类似,PointLightHelper用于PointLight对象。 要添加此帮助程序,请使用以下代码:


  // add point light
  var pointLight = new THREE.PointLight(0xffff00, 1.0);
  pointLight.position.set(300,300,300);
  this.scene.add(pointLight);
  var pointLightHelper = new THREE.PointLightHelper(pointLight, 50); // 50 is sphere size
  this.scene.add(pointLightHelper);

  // add point light
  var pointLight = new THREE.PointLight(0xffff00, 1.0);
  pointLight.position.set(300,300,300);
  this.scene.add(pointLight);
  var pointLightHelper = new THREE.PointLightHelper(pointLight, 50); // 50 is sphere size
  this.scene.add(pointLightHelper);

SpotLightHelper (SpotLightHelper)

Lastly, we added the spot light: the SpotLightHelper is for SpotLight object. To add this helper, use the following code:

最后,我们添加了聚光灯:SpotLightHelper用于SpotLight对象。 要添加此帮助程序,请使用以下代码:


  // add spot light
  var spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(-300,400,300);
  spotLight.castShadow = true;
  spotLight.shadowCameraFov = 60;
  this.scene.add(spotLight);
  var spotLightHelper = new THREE.SpotLightHelper(spotLight, 50); // 50 is sphere size
  this.scene.add(spotLightHelper);

  // add spot light
  var spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(-300,400,300);
  spotLight.castShadow = true;
  spotLight.shadowCameraFov = 60;
  this.scene.add(spotLight);
  var spotLightHelper = new THREE.SpotLightHelper(spotLight, 50); // 50 is sphere size
  this.scene.add(spotLightHelper);

现场演示
现场演示2

[sociallocker]

[社交储物柜]

打包下载

[/sociallocker]

[/ sociallocker]

结论 (Conclusion)

Stay tuned for new lessons and you are sure to find something new and interesting for yourself.

请继续关注新课程,您一定会发现适合自己的新事物。

翻译自: https://www.script-tutorials.com/webgl-with-three-js-lesson-3/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值