2
头图

这是一个底层基于WebGL开发的3D渲染引擎( 当然,后续是否会正式发布基于WebGPU的版本,也是可能的)。

和直接使用WebGL相比,比如着色器,大部分情况下你无需自己开发,不过,情况并不总是这样,如果你的需求太过特殊,我们依旧可以用更接近原生的方式来绘制,这是一个非常友好的设计。

绘制流程

一般最通用的绘制流程大致如下:

准备好场景准备好相机使用渲染器渲染出来

你可以提前看看我们最终要绘制的效果:

这是一个旋转的立方体。

你可以点击此处进行查看运行效果。

场景

所谓的场景,也就是空间的属性,就是当前空间里面有什么东西;比如:有什么物体(物体的材质、形状、尺寸)、有没有光(点光源还是环境光、或者平行光)等。

对我们这里而言,很明显,空间里有一个正六面体,而且,好像还有光照在上面。

那么,我们首先创建好场景,后续再补充场景中的内容:

var scene = new THREE.Scene();

网格模型

现在,我们来创建一个立方体:

var geometry = new THREE.BoxGeometry(100, 100, 100);

立方体是红色的,所以,还需要创建一个材质对象:

var material = new THREE.MeshLambertMaterial({
    color: "red"
});

然后,把立方体和材质对象关联起来,就获得了表示这个完整立方体信息的模型对象了:

var mesh = new THREE.Mesh(geometry, material);

最后,把这个立方体放到之前创建的空间中去:

scene.add(mesh);

光照

光一般有多种,比如环境光,其实我们就可以认为是漫反射,在原生代码中,我们需要自己设计光叠加的算法,而在这里,你只需要调用api设置参数即可:

var ambient = new THREE.AmbientLight("green");

同样的,也需要被添加到当前空间中去:

scene.add(ambient);

别的类型的光也类似,只是设置的参数不一样,这里就不再赘述了。

相机

其实就相当于你的眼睛的可视区域。空间中有什么,不代表你就应该看见什么,通过相机来确定你看的位置、方向、范围等。

还有一点需要特别说明,因为你看见的其实是平面,空间本身是3D的,那就存在一个投影算法,不同的投影算法最终你空间的内容也是不一样的(我们这里选择的是正射投影),整体来说比较好理解,直接看代码:

var width = window.innerWidth; //窗口宽度
var height = window.innerHeight; //窗口高度
var k = width / height; //窗口宽高比
var s = 100; //三维场景显示范围控制系数,系数越大,显示的范围越大

var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);

camera.position.set(200, 300, 200); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

渲染器

好了,空间准备好了,相机也准备好了,接下来就是渲染出来了。

首先,创建好渲染器:

var renderer = new THREE.WebGLRenderer();

然后,设置好参数:

renderer.setSize(width, height);//设置渲染区域尺寸
renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色

最终渲染的内容在哪里显示?当前是页面了,所以渲染器需要关联到页面中:

document.body.appendChild(renderer.domElement);

一切准备就绪,渲染即可:

renderer.render(scene, camera);

变换

相比最终的效果,我们绘制出来的是一个静止的,怎么办?

你可以修改相机的位置、角度等,或者改变物体的位置。比如这里,我们改变物体的位置:

mesh.rotateY(0.01);

同样的,改变完毕后,重新使用渲染器渲染即可。

更多

更多复杂的场景,也是在上面每步的调整,比如空间中有什么,不是只有上面的写法,你也可以使用顶点来自定义表示,只不过,上面的一个大体的思路,后续更丰富的学习,有了上面的大的架子,会更容易理解。

始终记住一点:难的绝不是3D本身,而是其背后一系列的算法和数学知识。不过,相信聪明的你,一定会轻松掌握这一切。

完整代码

原文地址

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/three@0"></script>
    <style>
        body {
            margin: 0;
        }
    </style>
</head>

<body>
    <script>

        // 【1】创建场景对象Scene
        var scene = new THREE.Scene();

        // 创建网格模型

        //创建一个立方体几何对象
        var geometry = new THREE.BoxGeometry(100, 100, 100);

        //材质对象Material
        var material = new THREE.MeshLambertMaterial({
            color: "red"
        });

        //网格模型对象Mesh
        var mesh = new THREE.Mesh(geometry, material);

        // 网格模型添加到场景中
        scene.add(mesh);

        // 光源设置

        //点光源
        var point = new THREE.PointLight("white");
        point.position.set(400, 200, 300); //点光源位置
        scene.add(point); //点光源添加到场景中

        //环境光
        var ambient = new THREE.AmbientLight("green");
        scene.add(ambient);

        // 【2】相机设置

        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 100; //三维场景显示范围控制系数,系数越大,显示的范围越大

        //创建相机对象
        var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);

        camera.position.set(200, 300, 200); //设置相机位置
        camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

        // 【3】创建渲染器对象

        var renderer = new THREE.WebGLRenderer();

        renderer.setSize(width, height);//设置渲染区域尺寸
        renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
        document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

        function render() {

            //执行渲染操作   指定场景、相机作为参数
            renderer.render(scene, camera);

            mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
            requestAnimationFrame(render);//请求再次执行渲染函数render

        }

        render();

    </script>
</body>

</html>

你好2007
179 声望4 粉丝

走一步,再走一步。