跳到主要内容

自定义几何体

Tinoe 内置的几种常用几何体不满足需求时,用户还可以使用 BufferGeometry创建自己定义的几何体,绘制出任意形状的几何体。

示例

使用

创建

const myGeom = new BufferGeometry();

上传数据

通过调用 .setAttribute(key: string, bufferData: BufferData),可以向新建的 BufferGeometry 实例中保存顶点属性数据。

// 上传顶点的位置数据
myGeom.setAttribute('position', {
data: positionData, // 数据
type: ComponentType.FLOAT, // 类型
itemSize: 3, // 每项大小
isPosition: true, // 是否是位置数据
bindingIdx: 1, // 属性数据所属的分组
bufferUsage: BufferUsage.Dynamic, // 动态数据,提醒底层该数据会动态更新,以优化使用
});

第一个参数接收一个字符串,作为顶点属性的名称,它需要严格与 Shader 中的属性名保持一致。 第二个参数接收一个BufferData类型的对象,该类型具体定义如下:

type BufferData = {
data?: TypedArray; // 数据源
type?: ComponentType; // 数据类型

itemSize?: number; // 每项数据大小
isIndex?: boolean; // 是否是索引属性数据,与isPosition只能有一个为true
isPosition?: boolean; // 是否是位置属性,与isIndex只能有一个为true

stride?: number; // 步长
bindingIdx?: number; // 所属的属性组,同一组的属性数据会被合并上传,以优化性能
bufferUsage?: BufferUsage; // 使用方式,用以优化底层实现

/** 仅供实例属性数据使用 **/
instanceCount?: number; // 实例个数
divisor?: number; // 前进数
};

对于ComponentTypeBufferUsage等类型的定义,请参考API 文档

宏开关

通过调用 .setMacro(key: string, enable: boolean),打开或关闭宏key

myGeom.setMacro('u_hasNormal', true); // 开启`u_hasNormal`的宏定义

包围盒

几何体的包围盒是射线拾取、视锥体裁剪优化的必需。有两种方法设置几何体的包围盒。

  1. .setBBox(min: Vector3, max: Vector3) 直接更新包围盒。
const min = new Vector3(-1, -1, -1);
const max = new Vector3(1, 1, 1);
myGeom.setBBox(min, max);
  1. .resetBBox(positionKey: string),根据位置属性数据自动计算包围盒,需要提供位置属性名称。
myGeom.resetBBox('position');

API

BufferGeometry

Q&A

  • 为什么上传索引数据,绘制失败?

    • 若控制台出现[.WebGL-0x480a60f800] GL_INVALID_ENUM: Enum is not currently supported.报错,请检测索引数据data的 TypeArray 类型是否为Uint32Array
  • 为什么属性数据不生效?

    • 请务必确保属性key与 Shader 中的 attribute 名称严格一致。
    • 请务必确保宏key与 Shader 中的 宏 名称严格一致。
    • 位置属性需要拥有独立的bindingIdx,不与其他属性共享。
  • 如果想搭配 Tinoe 内置材质使用,那属性取值就要和 Tinoe 内置的属性名相同,如下表。

    内置属性名解释
    a_position顶点位置
    a_texcoord纹理坐标
    a_normal法线
    a_tangent切线
    a_color颜色
  • 同样,宏取值也要和 Tinoe 内置的宏名称严格一致,如下表。

    内置属性名解释
    u_hasNormal存在法线属性,配合 a_normal 属性使用
    u_hasTangent存在切线属性,配合 a_tangent 属性使用
    u_hasVertexColor存在顶点颜色,配合 a_color 属性使用
    u_hasVertexAlpha存在顶点颜色透明度,配合 a_color 属性使用
    u_hasUV存在纹理坐标,配合 a_texcoord 属性使用
    u_enableInstance启动实例化渲染