WebGL ThreeJS学习总结三

https://github.com/newbieYoung/NewbieWebArticles/blob/master/webgl-threejs-3.html(2017-09-12T08:59:52Z)

© Young 2016-10-19 20:57
Welcome to My GitHub

概述

总结三主要是学习ThreeJS框架和一些数学知识等,包括相机、光线、形状、变换、视角控制、焦点控制、矩阵和弧度等;并根据所学知识实现一些稍复杂的效果。

比如:

简易魔方

概念

一、数学相关(math)

WebGL ThreeJS学习总结四中有关于四元数、欧拉角矩阵向量部分更详细的内容。

1、四元数、欧拉角

ThreeJS提供了两种三维旋转表达方式:欧拉角(euler)和四元数(quaternion),它们相比较使用矩阵的方式进行变换更加的节省存储空间和更方便的进行插值, 但是欧拉角(euler)存在万向锁问题。

讲真对于我这种数学渣来说着实有点复杂,下次再说…

2、矩阵 THREE.Matrix3、THREE.Matrix4

THREE.Matrix4表示4*4的矩阵;

THREE.Matrix3表示3*3的矩阵。

3、向量 THREE.Vector2、THREE.Vector3、THREE.Vector4

向量是数学、物理学和工程科学等多个自然科学中的基本概念,指一个同时具有大小和方向的几何对象。

ThreeJS中的相关类会复杂一些,比如THREE.Vector3可以表示3D空间中的点,也可以表示从(0,0,0)到(x,y,z)的向量,同时还可以表示任意顺序的一组数。

4、弧度

弧度是角的度量单位,缩写为rad,一周的弧度数位2π。

5、数学方法类 Three.Math

    /**
     * 如果value大于等于min且小于等于max则返回value
     * 如果value小于min则返回min
     * 如果value大于max则返回max
     */
    clamp ( value, min, max )

二、核心相关(core)

1、3D对象 THREE.Object3D

这是ThreeJS类库中大部分对象的基类,提供了一系列属性和操作方法在3D空间里边。

不推荐调用该对象的add方法,把某个另外对象作为子元素合并在该对象组中;官方建议的做法是利用Group对象合并。

Object3D对象的几何变化基本都是相对于物体本身的坐标系而言的,而且自身坐标系也跟着变化。

弧度是ThreeJS中的常用单位,比如Object3D对象的rotateY、rotateOnAxis等方法中参数单位就是弧度。

2、几何图形 THREE.Geometry

    var geometry = new THREE.Geometry();
    //vertices属性中包含该图形的所有顶点位置
    geometry.vertices.push(
        new THREE.Vector3( -10,  10, 0 ),
        new THREE.Vector3( -10, -10, 0 ),
        new THREE.Vector3(  10, -10, 0 )
    );


    /**
     * skinIndices属性指定当前序号顶点被哪些骨骼控制,蒙皮网格中每个顶点最多只能被四个骨骼控制;
     * 下述代码表明第15个顶点被第0、5、9、10个骨骼所控制。
     */
    geometry.skinIndices[15] = new THREE.Vector4(   0,   5,   9, 0 );
    /**
     * skinWeights属性指定当前序号顶点被指定骨骼控制的权重;
     * 下述代码表明第15个顶点被对应四个骨骼所控制的权重分别是20%、50%、30%、0%。
     */
    geometry.skinWeights[15] = new THREE.Vector4( 0.2, 0.5, 0.3, 0 );

3、对象组 THREE.Group

4、网格 THREE.Mesh

绘制3D图形最常用的一种方法就是使用网格(Mesh)

5、线条 THREE.Line

6、线条集合 THREE.LineSegments

7、球体 THREE.SphereGeometry

    /**
     * 构造函数:
     * radius表示球体半径;
     * widthSegments表示横向划分区域数量;
     * heightSegments表示纵向划分区域数量;
     * 其它不明
     */
    var geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength);

8、圆环 THREE.RingGeometry

    /**
     * 构造函数:
     * innerRadius表示内圆半径;
     * outerRadius表示外圆半径;
     * thetaSegments表示圆环圆度;
     * phiSegments表示内圆到外圆方向上的细分线段数;
     * thetaStart圆环面的起始角度;
     * thetaLength圆环面圆周弧长;
     */
    var geometry = new THREE.RingGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength);

9、缓存数据模型 THREE.BufferGeometry

这个类是另一种创建几何体对象的方式,它将所有的数据包括顶点位置、法线、面、颜色、uv和其它的自定义属性存储在缓冲区,用于减少GPU的负担;

我们在创建一些实例化后不经常操作的对象时,可以考虑使用这个类。

10、WebGL渲染器 THREE.WebGLRenderer

    /**
     * 构造函数:
     * antialias:true/false 用于设置是否开启反锯齿;
     * precision:highp/mediump/lowp 用于设置着色器精度;
     * alpha:true/false 用于设置背景色是否透明;
     */
    var render = new THREE.WebGLRenderer(parameters);

在我们使用ThreeJS开发WebAR项目时,需要设置WebGL背景透明,此时就需要用到alpha。

11、蒙皮网格 THREE.SkinnedMesh

支持骨骼动画的网格。

三、材质相关(material)

1、基础网孔材质 THREE.MeshBasicMaterial

2、基础线条材质 THREE.LineBasicMaterial

3、兰伯特材质 THREE.MeshLambertMaterial

一种非光滑表面材质没有高亮的镜面反射。

A material for non-shiny surfaces, without specular highlights.

    /**
     * 简单解释下构造函数里边的参数;
     * color表示漫反射光;
     * emissive表示自发光(可以简单理解为荧光,如果没有设置环境光,物体会表现为其自发光)。
     */
    var material = new THREE.MeshLambertMaterial({
        color:0xff00ff,
        emissive:0xdd4422
    });

surfaceColor = emissive + ambient + diffuse + specular;
上边公式表明物体表面的颜色是漫反射光(diffuse)、环境反射(ambient)、自发光(emissive)和镜面反射(specular)等光照作用的总和。
纹理主要是用来描述物体表面静态属性的对象,材质主要是用来描述物体表面动态属性的对象,比如处理光照等,不知道这么理解有没有问题。

4、自定义着色器 THREE.ShaderMaterial

一种自定义着色器,直接使用GLSL语言编写,运行在GPU;当ThreeJS没有提供某种材质时或者存在很多单一对象模型性能较低时,可以使用它。

四、加载器相关(loader)

1、纹理加载器 THREE.TextureLoader

    var loader = new THREE.TextureLoader();
    loader.load( 'textures/land_ocean_ice_cloud_2048.jpg', function ( texture ) {
        var geometry = new THREE.SphereGeometry( 100, 20, 20 );
        var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
        /**
         * 由于纹理加载属于异步流程,在回调函数把模型加入场景中后需要再次渲染才能显示出来
         */
        var mesh = new THREE.Mesh( geometry, material );
        render();//再次渲染
    },function ( xhr ) {
        console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
    },function ( xhr ) {
        console.log( 'An error happened' );
    });

2、加载管理工具 THREE.LoadingManager

用于存在多个加载器时,统一管理加载进度以及周期相关信息。

五、光照相关(light)

1、环境光 THREE.AmbientLight

环境光没有明确的光源位置,在各处形成的亮度也是一致的,光照颜色会添加到整个场景和所有对象的当前颜色上。

    //构造函数


    AmbientLight( color, intensity )


    color — 环境光颜色;
    intensity - 光照强度。

2、点光源 THREE.PointLight

点光源照到不同物体表面的亮度是线性递减的,因此离点光源距离越远的物体会显得越暗。

    //构造函数


    PointLight( color, intensity, distance, decay )


    color — 环境光颜色;
    intensity - 光照强度;
    distance - 设置光距离物体的距离;
    decay - 设置光的衰减量。

3、聚光等 THREE.SpotLight

聚光灯是一种特殊的点光源,它能够朝着一个方向投射类似圆锥形的光线;

    //构造函数


    SpotLight( color, intensity, distance, angle, penumbra, decay )


    //相比点光源多了两个参数
    angle — 聚光灯的张角;
    exponent - 光强在偏离目标的衰减指数。

所谓的目标是指如果想让聚光灯跟着某一物体移动,需要设置该物体为该聚光灯的目标

4、方向光、平行光 THREE.DirectionalLight

对于任意平行的平面,平行光照射的亮度都是相同的。

    //创建光线
    var directLight;
    function initLight() {
        directLight = new THREE.DirectionalLight(0xffffff);
        /**
         * 方向光的位置和物体的位置共同决定该方向光照射该物体的方向,
         * 也就是说如果物体位置在原点(0,0,0)那么方向光位置在(-1,0,0)或者(-80,0,0)对该物体而言意义一样。
         */
        directLight.position.set(-1,0,0);
        directLight.intensity = 1.5;
        scene.add(directLight);
    }

5、半球光 THREE.HemisphereLight

与环境光类似,但是这种光会从一种颜色渐变到另外一种颜色。

    //构造函数


    HemisphereLight(  skyColor, groundColor, intensity )


    skyColor — 场景上方的光的颜色;
    groundColor - 场景下方的光的颜色;
    intensity - 光照强度。

6、光照阴影

有光就应该有阴影,然而在ThreeJS中能形成阴影的光源只有THREE.DirectionalLightTHREE.SpotLight;而相对的能表现阴影效果的材质只有THREE.MeshLambertMaterialTHREE.MeshPhongMaterial

能表现阴影效果的材质稍微有点疑惑。

在场景中添加阴影效果,一般步骤如下:

(1)打开渲染器的阴影地图;

    renderer.shadowMap.enabled = true;//打开渲染器的阴影地图

(2)使用支持阴影的光源,并设置相关参数;

    shadowLight = new THREE.DirectionalLight(0xffffff, .9);
    shadowLight.position.set(150,350,350);
    shadowLight.castShadow = true;//开启光源投影


    //定义可见域的投射阴影
    shadowLight.shadow.camera.left = -400;
    shadowLight.shadow.camera.right = 400;
    shadowLight.shadow.camera.top = 400;
    shadowLight.shadow.camera.bottom = -400;
    shadowLight.shadow.camera.near = 1;
    shadowLight.shadow.camera.far = 1000;


    //定义阴影的分辨率;虽然分辨率越高越好,但是需要付出更加昂贵的代价维持高性能的表现
    shadowLight.shadow.mapSize.width = 2048;
    shadowLight.shadow.mapSize.height = 2048;

(3)对被照的物体启用阴影的产生;

    cube.castShadow = true;//开启阴影产生

(4)对投射的物体启用接受阴影。

    floor.receiveShadow = true; //接受阴影

六、相机相关(camera)

1、透视投影相机 THREE.PerspectiveCamera

    /**
     * 构造函数:
     * fov表示可视角度;
     * aspect表示裁剪面宽高比;
     * near表示近端距离;
     * far表示远端距离;
     * 只有离相机的距离大于near值小于far值,且在相机的可视角度之内,才能被相机投影到。
     */
    var camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

2、正交投影相机 THREE.OrthographicCamera

    /**
     * 构造函数:
     * left左侧面
     * right右侧面
     * top上侧面
     * bottom下侧面
     * near近侧面
     * far远侧面
     * 这六个侧面所围成的内部区域就是相机投影的可视区域
     * @type {THREE}
     */
    var camera = new THREE.OrthographicCamera( left, right, top, bottom, near, far );

七、动画相关(animation)

1、混合动画播放器 THREE.AnimationMixer

场景中特定物体的动画播放器,如果场景中的多个物体的动画是相互独立的,则每个单独动画都可以使用单独的AnimationMixer对象来处理。

八、其它(other)

1、视角控制

ThreeJS提供包括orbitcontrols和trackballcontrols等多种视角控制类库支持,暂时只了解基本用法。
ThreeJS提供基于手机陀螺仪的3D绕环视角控制器DeviceOrientationControls,详细内容请查看ThreeJS的DeviceOrientationControls源代码解析

2、焦点控制 Three.Raycaster

Three.Raycaster被设计用来判断鼠标焦点是否在空间的某个物体上,暂时只了解基本用法,另外要注意获取焦点元素不能放在渲染方法里边执行否则移动端会有问题。

示例程序

发表评论

电子邮件地址不会被公开。 必填项已用*标注