3D 扩展

    加载3D渲染库的方式非常简单,你可以直接通过CND加载

    只要确保加载在spritejs的JS之后即可。

    💡考虑到最佳性能,sprite-extend-3d.js默认适配chrome59及以上浏览器,所以你只要用spritejs的ES编译版本即可。如果你希望支持较早的浏览器,sprite-extend-3d.js仍可支持早期版本,不过你需要在项目中修改babel配置,重新编译适配旧浏览器的版本。

    加载之后,可以通过spritejs.ext3d来访问3D的API,并且可以通过scene.layer3d(layerID)来创建3D的渲染层。

    1. const {Scene} = spritejs;
    2. const {Cube, shaders} = spritejs.ext3d;
    3. const container = document.getElementById('container');
    4. const scene = new Scene({container});
    5. const layer = scene.layer3d('fglayer', {
    6. camera: {
    7. fov: 35, // Field of view
    8. },
    9. });
    10. layer.camera.attributes.pos = [3, 3, 5];
    11. const program = layer.createProgram({
    12. ...shaders.NORMAL_GEOMETRY,
    13. cullFace: null,
    14. });
    15. const cube = new Cube(program, {
    16. colors: 'red red blue blue green green',
    17. });
    18. layer.append(cube);
    19. layer.setOrbit(); // 开启旋转控制

    当然,你也可以通过模块方式加载sprite-extend-3d

    1. import {Scene} from 'spritejs';
    2. import {Cube, shaders} from 'sprite-extend-3d';

    坐标和相机

    与2D的layer不同,layer3d采用WebGL坐标系,画布中心点的位置是[0,0,0],水平向右是x轴,垂直向上是y轴,垂直于屏幕向外的是z轴。

    元素是否显示出来,显示在什么位置,与透视相机有关。

    一个layer对应一个默认的透视相机,创建layer的时候可以初始化它,在后续渲染的时候也可以修改它的属性。上面的例子中,我们把相机放在坐标[3, 3, 5]的位置。

    透视相机有一些参数,如下:

    • near: 相机可以拍摄到的最近距离,默认为 0.1
    • far: 相机可以拍摄到的最远距离,默认为 100
    • fov: 视野宽度,默认是45度
    • aspect: 宽高比,默认是1:1,但是如果preserveAspect配置不为false,layer会根据resolution来设置相机的宽高比
    • preserveAspect: 默认为true,根据画布宽高比来保持相机宽高比,这样元素就不会被拉伸或压缩

    默认情况下,相机的方向是朝着z轴负向无穷远处,而相机有一个方法叫lookAt,传入一个坐标,可以让相机朝向该位置拍摄。

    在3D的layer中,只要有顶点坐标就可以非常方便地绘制几何体。

    上面的代码中,我们传入一组顶点坐标,绘制了一个正四面体。

    绘制模型

    1. const {Scene} = spritejs;
    2. const {Mesh3d, shaders} = spritejs.ext3d;
    3. const container = document.getElementById('container');
    4. const scene = new Scene({
    5. container,
    6. displayRatio: 2,
    7. });
    8. const layer = scene.layer3d('fglayer', {
    9. camera: {
    10. fov: 45,
    11. pos: [-2, 2, 2],
    12. },
    13. directionalLight: [0.5, 1.0, -0.3, 0.15],
    14. });
    15. const program = layer.createProgram(shaders.NORMAL);
    16. const model = layer.loadModel('https://s2.ssl.qhres.com/static/bf607b5f64a91492.json');
    17. const macow = new Mesh3d(program, {model});
    18. layer.setOrbit({target: [0, 0.7, 0]});

    注意上面的代码里layer.loadModel是个异步方法,但是我们并不用等到model数据真正加载下来,可以直接把model(此时是一个promise)赋给Mesh3d元素,等数据加载完毕后,元素就会被渲染出来。

    有了模型,我们可以把纹理加上:

    1. const {Mesh3d, shaders} = spritejs.ext3d;
    2. const container = document.getElementById('container');
    3. const scene = new Scene({
    4. container,
    5. displayRatio: 2,
    6. });
    7. const layer = scene.layer3d('fglayer', {
    8. camera: {
    9. fov: 45,
    10. pos: [-2, 2, 2],
    11. },
    12. directionalLight: [0.5, 1.0, -0.3, 0.15],
    13. });
    14. const texture = layer.createTexture('https://p1.ssl.qhimg.com/t01b4bd0e2fb9f47550.jpg');
    15. const program = layer.createProgram({
    16. ...shaders.NORMAL_TEXTURE,
    17. texture,
    18. });
    19. const model = layer.loadModel('https://s2.ssl.qhres.com/static/bf607b5f64a91492.json');
    20. const macow = new Mesh3d(program, {model});
    21. layer.append(macow);
    22. layer.setOrbit({target: [0, 0.7, 0]});

    我们只要通过layer.createTexture创建texture对象,并将该对象赋给program(同时要将programe的shader类型改为NORMAL_TEXTURE),这样元素的纹理就能显示出来。注意createTexture方法也是一个异步方法,但我们同样不用等待图片加载完毕再创建元素。

    SpriteJSNext默认支持几种常见的光源,我们可以设置环境光(ambientColor),方向光(directionalLight)和点光源(pointLight)。

    与元素交互

    SpriteJSNext的3D扩展中,与元素交互也非常简单,在前面的例子我们已经见过。

    一种交互是通过鼠标或触屏旋转角度和缩放,只需要一条语句:

    1. layer.setOrbit({target: [x, y, z]});

      有了这条语句之后,我们就可以在元素上像2D那样注册鼠标或触屏事件了。