three.js之缓冲类型几何体顶点

专栏目录请点击

简介

  • 顶点一般使我们在创建模型的时候使用的,他一般对应buffer类型的几何体,使用BufferGeometry创建 点击
  • 我们还会用到BufferAttribute来设置相应的属性,如顶点位置向量,面片索引,法向量,颜色值,UV坐标以及任何自定义 attribute 点击

构成

顶点是由两个元素组成的

  1. 顶点的位置
  2. 顶点的颜色

代码

顶点构成图形

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>第一个three.js文件_WebGL三维场景</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            /* 隐藏body窗口区域滚动条 */
        }
    </style>
    <!--引入three.js三维引擎-->
    <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
    <script src="http://www.yanhuangxueyuan.com/threejs/examples/js/controls/OrbitControls.js"></script>
</head>

<body>
    <script>
        /**
         * 创建场景对象Scene
         */
        var scene = new THREE.Scene();
        /**
         * 创建网格模型
         */
        var geometry = new THREE.BufferGeometry(); //创建一个Buffer类型几何体对象
        //类型数组创建顶点数据
        var vertices = new Float32Array([
            0, 0, 0, //顶点1坐标
            50, 0, 0, //顶点2坐标
            0, 100, 0, //顶点3坐标
            0, 0, 10, //顶点4坐标
            0, 0, 100, //顶点5坐标
            50, 0, 10, //顶点6坐标
        ]);
        // 创建属性缓冲区对象
        var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组,表示一个顶点的xyz坐标
        // 设置几何体attributes属性的位置属性
        geometry.attributes.position = attribue;
        const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        const mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);
        // 辅助坐标系  参数250表示坐标系大小,可以根据场景大小去设置
        var axisHelper = new THREE.AxisHelper(250);
        scene.add(axisHelper);
        /**
         * 光源设置
         */
        //点光源
        var point = new THREE.PointLight(0xffffff); // 参数为光照强度
        point.position.set(400, 200, 300); //点光源位置
        scene.add(point); //点光源添加到场景中
        //环境光
        var ambient = new THREE.AmbientLight(0x444444);
        scene.add(ambient);
        // console.log(scene)
        // console.log(scene.children)
        /**
         * 相机设置
         */
        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
        //创建相机对象
        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); //body元素中插入canvas对象
        // 渲染函数
        function render() {
            renderer.render(scene, camera);//执行渲染操作
        }
        render();
        var controls = new THREE.OrbitControls(camera, renderer.domElement);//创建控件对象
        controls.addEventListener('change', render);//监听鼠标、键盘事件
    </script>
</body>

</html>

在这里插入图片描述

核心代码

var geometry = new THREE.BufferGeometry(); //创建一个Buffer类型几何体对象
//类型数组创建顶点数据
var vertices = new Float32Array([
    0, 0, 0, //顶点1坐标
    50, 0, 0, //顶点2坐标
    0, 100, 0, //顶点3坐标
    0, 0, 10, //顶点4坐标
    0, 0, 100, //顶点5坐标
    50, 0, 10, //顶点6坐标
]);
// 创建属性缓冲区对象
var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组,表示一个顶点的xyz坐标
// 设置几何体attributes属性的位置属性
geometry.attributes.position = attribue;
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

顶点的位置与颜色

var geometry = new THREE.BufferGeometry(); //声明一个缓冲几何体对象

//类型数组创建顶点位置position数据
var vertices = new Float32Array([
    0, 0, 0, //顶点1坐标
    50, 0, 0, //顶点2坐标
    0, 100, 0, //顶点3坐标

    0, 0, 10, //顶点4坐标
    0, 0, 100, //顶点5坐标
    50, 0, 10, //顶点6坐标
]);
// 创建属性缓冲区对象
var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组,作为一个顶点的xyz坐标
// 设置几何体attributes属性的位置position属性
geometry.attributes.position = attribue;
//类型数组创建顶点颜色color数据
var colors = new Float32Array([
    1, 0, 0, //顶点1颜色
    0, 1, 0, //顶点2颜色
    0, 0, 1, //顶点3颜色

    1, 1, 0, //顶点4颜色
    0, 1, 1, //顶点5颜色
    1, 0, 1, //顶点6颜色
]);
// 设置几何体attributes属性的颜色color属性
geometry.attributes.color = new THREE.BufferAttribute(colors, 3); //3个为一组,表示一个顶点的颜色数据RGB
//材质对象
var material = new THREE.PointsMaterial({
    // 使用顶点颜色数据渲染模型,不需要再定义color属性
    // color: 0xff0000,
    vertexColors: THREE.VertexColors, //以顶点颜色为准
    size: 10.0 //点对象像素尺寸
});
// 点渲染模式  点模型对象Points
var points = new THREE.Points(geometry, material); //点模型对象
scene.add(points); //点对象添加到场景
// 辅助坐标系  参数250表示坐标系大小,可以根据场景大小去设置
var axisHelper = new THREE.AxisHelper(250);
scene.add(axisHelper);

在这里插入图片描述
我们会发现他是一一对应的关系

  • 这里的材质的颜色设置,我们使用的是VertexColors这个属性,并不是使用的color属性
    • 他的默认值是THREE.NoColor,也就是说模型的颜色渲染效果取决于材质属性.color,如果把材质属性VertexColors的值设置为THREE.VertexColors,那么他进行渲染的时候就会使用几何体顶点的颜色数据geometry.attributes.color

BufferAttribute

这个属性是为了提供各种各样符合顶点的数据,比如顶点的颜色,顶点的位置数据,提供顶点属性的值,如geometry.attributes.position

颜色差值

当我们把下面代码

//材质对象
var material = new THREE.PointsMaterial({
    // 使用顶点颜色数据渲染模型,不需要再定义color属性
    // color: 0xff0000,
    vertexColors: THREE.VertexColors, //以顶点颜色为准
    size: 10.0 //点对象像素尺寸
});
// 点渲染模式  点模型对象Points
var points = new THREE.Points(geometry, material); //点模型对象
scene.add(points); //点对象添加到场景

修改成

//材质对象
var material = new THREE.MeshBasicMaterial({vertexColors: THREE.VertexColors,});
// 点渲染模式  点模型对象Points
var points = new THREE.Mesh(geometry, material); //点模型对象
scene.add(points); //点对象添加到场景

我们会发现他的渲染效果如下
在这里插入图片描述

  • 他呈现出一种渐变效果,之所以成年初渐变效果,是因为webgl进行渲染的时候会对于颜色数据进行差值计算
    • 比如端点1设置为红色,端点2设置为蓝色,那么整个线条会呈现出点1到点2红色到蓝色的渐变
    • 对于网格模型Mesh来说,就是餐侥幸的三个顶点分别设置一个颜色,三角形内部的区域像素会根据这三个顶点的颜色进行渲染计算
  • 插值计算示意图
    • 在这里插入图片描述

法向量

  • webgl中为了计算光线与物体表面入射角,首先要计算物体表面每个位置的法线方向
  • 在网格模型中,曲面是有一个一个三角形构成,为了表示物体表面各个位置的发现方向,我们可以给几何体的每个顶点定义一个方向向量

在这里插入图片描述

不设置法向量

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>顶点法向量光照计算</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            /* 隐藏body窗口区域滚动条 */
        }
    </style>
    <!--引入three.js三维引擎-->
    <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
    <!-- 引入threejs扩展控件OrbitControls.js -->
    <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>
</head>

<body>
    <script>
        /**
         * 创建场景对象Scene
         */
        var scene = new THREE.Scene();
        /**
         * 创建网格模型
         */
        var geometry = new THREE.BufferGeometry(); //声明一个空几何体对象
        //类型数组创建顶点位置position数据
        var vertices = new Float32Array([
            0, 0, 0, //顶点1坐标
            50, 0, 0, //顶点2坐标
            0, 100, 0, //顶点3坐标

            0, 0, 0, //顶点4坐标
            0, 0, 100, //顶点5坐标
            50, 0, 0, //顶点6坐标

        ]);
        // 创建属性缓冲区对象
        var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组
        // 设置几何体attributes属性的位置position属性
        geometry.attributes.position = attribue

        //材质对象
        var material = new THREE.MeshLambertMaterial({
            color: 0x0000ff, //三角面颜色
            side: THREE.DoubleSide //两面可见
        });
        var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
        scene.add(mesh); //网格模型添加到场景中

        // 辅助坐标系
        var axisHelper = new THREE.AxisHelper(250);
        scene.add(axisHelper);
        /**
         * 光源设置
         */
        //点光源
        var point = new THREE.PointLight(0xffffff);
        point.position.set(400, 200, 300); //点光源位置
        scene.add(point); //点光源添加到场景中
        //环境光
        var ambient = new THREE.AmbientLight(0x444444);
        scene.add(ambient);
        /**
         * 相机设置
         */
        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 150; //三维场景显示范围控制系数,系数越大,显示的范围越大
        //创建相机对象
        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); //body元素中插入canvas对象

        // 渲染函数
        function render() {
            renderer.render(scene, camera); //执行渲染操作
        }
        render();
        //创建控件对象  相机对象camera作为参数   控件可以监听鼠标的变化,改变相机对象的属性
        var controls = new THREE.OrbitControls(camera, renderer.domElement);
        //监听鼠标事件,触发渲染函数,更新canvas画布渲染效果
        controls.addEventListener('change', render);
    </script>

</body>

</html>

上面的代码没有设置法向量,他渲染的图形是下面这个样子的

在这里插入图片描述

  • 我们可以看到,整个图形就像是没有光照一样,但是当我们加上了下面的代码
var normals = new Float32Array([
    0, 0, 1, //顶点1法向量
    0, 0, 1, //顶点2法向量
    0, 0, 1, //顶点3法向量

    0, 1, 0, //顶点4法向量
    0, 1, 0, //顶点5法向量
    0, 1, 0, //顶点6法向量
]);
// 设置几何体attributes属性的位置normal属性
geometry.attributes.normal = new THREE.BufferAttribute(normals, 3); //3个为一组,表示一个顶点的法向量数据

他的渲染就是下面这个样子的
在这里插入图片描述
这样就有了光的散射

  • 所以,我们在集合体中,常用的属性如下
// 访问几何体顶点位置数据
BufferGeometry.attributes.position
// 访问几何体顶点颜色数据
BufferGeometry.attributes.color
// 访问几何体顶点法向量数据
BufferGeometry.attributes.normal

顶点索引

使用顶点索引的目的是用来复用顶点数据,什么是复用顶点数据呢,比如,下面这个矩形

在这里插入图片描述

  1. 这个矩形是用两个三角形拼凑而成,如果要定义顶点的话,那么需要定义6个顶点
  2. 但是我们会发现两个三角形有两个顶点的位置是重合的,而对于这些重合的顶点,我们可以值定义一次

不复用顶点

如果不复用顶点的话,我们需要定义6个顶点

/**
 * 创建网格模型
 */
var geometry = new THREE.BufferGeometry(); //声明一个空几何体对象
//类型数组创建顶点位置position数据
var vertices = new Float32Array([
    0, 0, 0, //顶点1坐标
    80, 0, 0, //顶点2坐标
    80, 80, 0, //顶点3坐标

    0, 0, 0, //顶点4坐标   和顶点1位置相同
    80, 80, 0, //顶点5坐标  和顶点3位置相同
    0, 80, 0, //顶点6坐标
]);
// 创建属性缓冲区对象
var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组
// 设置几何体attributes属性的位置position属性
geometry.attributes.position = attribue
var normals = new Float32Array([
    0, 0, 1, //顶点1法向量
    0, 0, 1, //顶点2法向量
    0, 0, 1, //顶点3法向量

    0, 0, 1, //顶点4法向量
    0, 0, 1, //顶点5法向量
    0, 0, 1, //顶点6法向量
]);
// 设置几何体attributes属性的位置normal属性
geometry.attributes.normal = new THREE.BufferAttribute(normals, 3); //3个为一组,表示一个顶点的xyz坐标

渲染如下

在这里插入图片描述

复用顶点

我们先定义顶点

var geometry = new THREE.BufferGeometry(); //声明一个空几何体对象
//类型数组创建顶点位置position数据
var vertices = new Float32Array([
  0, 0, 0, //顶点1坐标
  80, 0, 0, //顶点2坐标
  80, 80, 0, //顶点3坐标
  0, 80, 0, //顶点4坐标
]);
// 创建属性缓冲区对象
var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组
// 设置几何体attributes属性的位置position属性
geometry.attributes.position = attribue
var normals = new Float32Array([
  0, 0, 1, //顶点1法向量
  0, 0, 1, //顶点2法向量
  0, 0, 1, //顶点3法向量
  0, 0, 1, //顶点4法向量
]);
// 设置几何体attributes属性的位置normal属性
geometry.attributes.normal = new THREE.BufferAttribute(normals, 3); //3个为一组,表示一个顶点的xyz坐标

然后我们去定义复用的索引

// Uint16Array类型数组创建顶点索引数据
var indexes = new Uint16Array([
  // 0对应第1个顶点位置数据、第1个顶点法向量数据
  // 1对应第2个顶点位置数据、第2个顶点法向量数据
  // 索引值3个为一组,表示一个三角形的3个顶点
  0, 1, 2,
  0, 2, 3,
])
// 索引数据赋值给几何体的index属性
geometry.index = new THREE.BufferAttribute(indexes, 1); //1个为一组

我们可以看注释,也可以看下面的解释

  1. 在数组中一个数字代表一个顶点,三个数字代表一个三角形数据
  2. 0表示第一个顶点数据,1表示第二个顶点的数据,一次类推
  3. 我们可以看到一个数组中有两个重复的数据即 0和2,也就是说第一个和第三个顶点被复用
  • 在创建顶点索引的时候,可以根据顶点的数量选择类型数组
  • 对于顶点索引而言要选择整形类的数组,非索引的顶点数据,可以选择浮点类型的数组,如Float32Array
类型数组位数字节类型描述C语言等价类型
Int8Array81有符号8位整型int8_t
Uint8Array81无符号8位整型uint8_t
Int16Array162有符号16位整型 int16_t
Uint16Array162无符号16位整型int16_t
Int32Array324有符号32位整型int32_t
Uint32Array324无符号32位整型uint32_t
Float32Array324单精度(32位)浮点数float
Float64Array648双精度(64位)浮点数double
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值