【GT】Assembler 源码解读及使用 !Cocos Creator!

原文链接:  https://forum.cocos.org/t/demo/95087
作者: GT
排版整理: 白玉无冰

背景

自定义渲染可以实现很多酷炫的 shader 特效,目前常用的有两种方法:

  • 创建自定义材质,给材质增加参数。这个参数会作为 uniform 变量传入 shader 由于渲染合批要求材质参数保持一致,所以如果大量对象使用自定义材质时,并且材质参数各不相同,是无法进行合批渲染的,一个对象占一个 draw call

  • 创建自定义 assembler,在顶点数据输入渲染管道前修改它的值 这种方式比较灵活,如果需要输入更多自定义参数,标准的顶点格式就不够用了

本文介绍另一种方法,即能让shader获得自定义参数,又能让自定义材质合批渲染。这种方法就是自定义顶点格式

Assembler详解

Assembler是实现本文相关功能的核心类,先简单回顾一下官方文档里介绍的内容 https://docs.cocos.com/creator/manual/zh/advanced-topics/custom-render.html

Assembler 中必须要定义 updateRenderDatafillBuffers 方法 前者需要更新准备顶点数据,后者则是将准备好的顶点数据填充进 VetexBufferIndiceBuffer

2D渲染中,Assember2D类是一个重要的基础类,最常用的cc.Sprite的各种模式(Simple,平铺,九宫格)在内部都对应了不同的Assembler派生类。同样是一个四边形的节点,不同的Assembler可以将其转化成不同数量的顶点实现不同的渲染效果

  • Simple模式下是常规的四边形,有4个顶点。(利用这个可以实现渐变色效果)

  • 平铺模式下Assembler根据纹理的重复次数对节点进行“拆碎”,相当于每重复一次就产生1个四边形。(利用这个可以实现顶点动画之水纹旗子)

  • 九宫格模式下Assembler将节点拆分为9个四边形,每个四边形对应纹理上的一个“格子”

fillBuffers源码解读

先看看Assembler2D是如何实现 fillBuffers 的 源码位置:https://github.com/cocos-creator/engine/blob/master/cocos2d/core/renderer/assembler-2d.js

    fillBuffers (comp, renderer) {
       // 如果节点的世界坐标发生变化,重新从当前节点的世界坐标计算一次顶点数据
        if (renderer.worldMatDirty) {
            this.updateWorldVerts(comp);
        }

       // 获取准备好的顶点数据
       // vData包含pos、uv、color数据
       // iData包含三角剖分后的顶点索引数据
        let renderData = this._renderData;
        let vData = renderData.vDatas[0];
        let iData = renderData.iDatas[0];

       // 获取顶点缓存
       // getBuffer()方法后面会被我们重载,以便获得支持自定义顶点格式的缓存
        let buffer = this.getBuffer(renderer);

       // 获取当前节点的顶点数据对应最终buffer的偏移量
       // 可以简单理解为当前节点和其他同格式节点的数据,都将按顺序追加到这个大buffer里
        let offsetInfo = buffer.request(this.verticesCount, this.indicesCount);

        // fill vertices
        let vertexOffset = offsetInfo.byteOffset >> 2,
            vbuf = buffer._vData;

       // 将准备好的vData拷贝到VetexBuffer里。这里会判断如果buffer装不下了,vData会被截断一部分
       // 通常是因为节点数量太多导致的,从下个节点开始会使用新的buffer,也就是重新开一个合批
       // 当前节点的数据被截断后,则只能被渲染一部分(推测)
        if (vData.length + vertexOffset > vbuf.length) {
            vbuf.set(vData.subarray(0, vbuf.length - vertexOffset), vertexOffset);
        } el
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值