cocoscreator性能优化4-Sprite颜色数据去除

news2024/11/20 15:27:39

前言

 

Sprite是游戏内容的一个基本组成元素,包括ui、道具、立绘等各种地方都会用到。大部分情况下美术会帮我们调好图片颜色,我们只要把图片直接放到游戏里就行了。Sprite默认的渲染顶点数据中包含了颜色数据,由于我们并不需要去修改颜色,某些情况下这似乎是一个不必要的东西。

去年底的时候,由于希望在性能优化方面做一些研究,在论坛找到了江南百景图研发负责人的技术分享文章,其中提到:

优化 Shader 的输入数据

由于《江南百景图》的图片资源中不会用到 Color 这个属性,因此在材质中,我们将原有的 Color 数据去除掉。

将原有的 Color 数据去除掉。用来存放项目中所需要的其它信息,这样做可以减少 CPU 与 GPU 互相传输的数据量。

本文参照文章中的思路实现了这个优化。

开发环境

浏览器:Chrome

开发语言:JavaScript

引擎版本:CocosCreator 2.4.3

词语缩写对照

顶点格式:顶点数据格式。

研究过程

按照思路,需要改动Sprite渲染相关代码,以及修改对应的材质。

翻源码找出,Sprite对应的assembler是SimpleSpriteAssembler(渲染模式为simple时)

源码位于:cocos2d\core\renderer\webgl\assemblers\sprite\2d\simple.js

其继承关系为:cc.Assembler->cc.Assembler2D->SimpleSpriteAssembler。

缕清关系后,我们要找出顶点数据格式是在哪定义的。assembler用于填充顶点数据,所以我们到Assembler.js中找找。

import { vfmtPosUvColor } from './webgl/vertex-format';
export default class Assembler {
    getVfmt () {
        return vfmtPosUvColor;
    }
}

找到了!默认顶点格式就是这个vfmtPosUvColor

var vfmtPosUvColor = new gfx.VertexFormat([
    { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
    { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
    { name: gfx.ATTR_COLOR, type: gfx.ATTR_TYPE_UINT8, num: 4, normalize: true },
]);

从vfmtPosUvColor的定义可以看出,顶点数据中含有三个数据(括号里的英文对应材质中的输入变量名):

  1. ATTR_POSITION(a_position 位置)
  2. ATTR_UV0(a_uv0 uv)
  3. ATTR_COLOR(a_color 颜色)

很明显ATTR_COLOR就是我们今天的目标

弄清楚顶点格式后,下一步是找到填充这些数据的地方。

顶点数据保存于RenderData,这三个数据是分开填充的,避免有些时候只需要更新其中一个(如只是移动了位置),却要全部跑一遍。顶点数据填充时,是按定义好的顺序填充的,此处引用论坛文章的图:

由于我们只是去除最后的color,所以位置和uv的填充函数是不需要修改的(在一个顶点数据中的相对位置没有发生改变)。

找出颜色填充函数,updateColor函数声明于assembler-2d.js。

updateColor (comp, color) {
    let uintVerts = this._renderData.uintVDatas[0];
    if (!uintVerts) return;
    color = color != null ? color : comp.node.color._val;
    let floatsPerVert = this.floatsPerVert;
    let colorOffset = this.colorOffset;
    for (let i = colorOffset, l = uintVerts.length; i < l; i += floatsPerVert) {
        uintVerts[i] = color;
    }
}

函数中将颜色值填充在每个顶点数据的末尾(position和uv之后)。我们需要修改updateColor函数,因为不再需要填充颜色值了

实现思路

看完又是要改源码了。不过还是可以通过继承相关类实现。继承方案相对来说会比较麻烦,但在实验阶段需要频繁修改时会更方便快速。

我们需要自定义Sprite、Assembler、Material、Effect。分别命名为NoColorSprite、NoColorSpriteAssembler、noColorMaterial、noColorEffect。

需求可拆分为如下实现步骤:

  1. 新建noColorEffect及noColorMaterial,在内置的代码基础上,去除颜色相关内容。
  2. 新建NoColorSpriteAssembler,新建顶点格式,并重写/实现渲染数据填充的相关函数。
  3. 新建NoColorSprite,将默认的assembler改为我们自己的NoColorSpriteAssembler。

代码

第一步是effect和material,主要工作是删代码(颜色相关的)... 新建的material只要将effect引用改为noColorEffect即可。

// 删除颜色相关输入输出处理
CCProgram vs %{
  precision highp float;

  #include <cc-global>
  #include <cc-local>

  in vec3 a_position;

  #if USE_TEXTURE
  in vec2 a_uv0;
  out vec2 v_uv0;
  #endif

  void main () {
    vec4 pos = vec4(a_position, 1);

    #if CC_USE_MODEL
    pos = cc_matViewProj * cc_matWorld * pos;
    #else
    pos = cc_matViewProj * pos;
    #endif

    #if USE_TEXTURE
    v_uv0 = a_uv0;
    #endif


    gl_Position = pos;
  }
}%

// 删除颜色相关输入处理 输出颜色直接取像素颜色
CCProgram fs %{
  precision highp float;
  
  #include <alpha-test>
  #include <texture>

  #if USE_TEXTURE
  in vec2 v_uv0;
  uniform sampler2D texture;
  #endif

  void main () {
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      CCTexture(texture, v_uv0, o);
    #endif

    ALPHA_TEST(o);

    gl_FragColor = o;
  }
}%

接着,创建NoColorSpriteAssembler.js,自定义顶点格式,去掉默认的颜色字段

let gfx = cc.gfx;
let vfmtNoColor = new gfx.VertexFormat([
    { name: gfx.ATTR_POSITION, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },
    { name: gfx.ATTR_UV0, type: gfx.ATTR_TYPE_FLOAT32, num: 2 },        // texture纹理uv
]);

我们只是想去除颜色,可以通过继承cc.Assembler实现noColorMaterial,其他渲染相关代码则可以从Assembler2D及SimpleSpriteAssembler中复制。这里贴出主要的代码。

因为我们修改了顶点格式,需要同步修改相关值。这里重写构造函数进行修改。

floatsPerVert是顶点格式数据长度(用浮点数计算),原本是5个浮点数,这里去掉了颜色,所以改为4。其他数据照抄Assembler2D中的值即可。

export default class NoColorAssembler extends cc.Assembler {
    constructor () {
        super();

        // uv在顶点数据中的偏移位置(前面有两个float的值表示position)
        this.uvOffset = 2;
        // 每个顶点的浮点数数量(position 2浮点数,uv 2浮点数)
        this.floatsPerVert = 4;

        // 顶点数量 (可以用4个点来表示两个三角形)
        this.verticesCount = 4;
        // 顶点索引数量 (两个三角形共6个顶点索引) 这个部分可以看链接中的文章有说明。
        this.indicesCount = 6;

        this.initData();
        this.initLocal();
    }
}

修改顶点数据格式后,我们需要一个不一样的RenderData来存储这些数据,模仿Assembler2D实现initData函数,在里面按我们定义的格式创建RenderData

/**
* 初始化this._renderData 仿照Assembler2D.initData 创建自定义格式的renderData
*/
initData () {
    let data = this._renderData = new cc.RenderData();
    this._renderData.init(this);
    
    // 按我们自己的格式创建RenderData
    data.createFlexData(0, this.verticesCount, this.indicesCount, this.getVfmt());
    
    // createFlexData不会填充顶点索引信息,手动补充一下 仿照cc.RenderData.initQuadIndices
    let indices = data.iDatas[0];
    let count = indices.length / 6;
    for (let i = 0, idx = 0; i < count; i++) {
        let vertextID = i * 4;
        indices[idx++] = vertextID;
        indices[idx++] = vertextID+1;
        indices[idx++] = vertextID+2;
        indices[idx++] = vertextID+1;
        indices[idx++] = vertextID+3;
        indices[idx++] = vertextID+2;
    }
}

再之后是本文的重点,把颜色的填充功能去掉

/**
* 更新颜色 啥也不干😆
*/
updateColor () {
}

最后,改动顶点数据格式后还有一些需要同步修改的地方。

/**
* 获得存放自定义顶点数据的buffer
* @returns {cc.MeshBuffer}
*/
getBuffer() {
    return cc.renderer._handle.getBuffer("mesh", this.getVfmt());
}
/**
* 获得顶点数据格式
* 重写 返回自定义的顶点数据格式
* @returns {cc.gfx.VertexFormat}
*/
getVfmt () {
    return vfmtNoColor;
}

代码有点长,没有全部贴出来。可以在后面的源码附件中查看,其他函数基本是从Assembler2D及SimpleSpriteAssembler复制出来的。

最最最后,如果产生一些如继承、函数为空之类的报错,可以在creator.d.ts文件中增加以下声明。

declare namespace cc {
	export class Assembler {
		public _renderComp: cc.RenderComponent;
		public init(comp: cc.RenderComponent);
		public getVfmt();
		static public register(renderCompCtor, assembler);
	}
	export class RenderData {
		init(assembler: cc.Assembler);
		createQuadData(index, verticesFloats, indicesCount);
		createFlexData(index, verticesFloats, indicesCount, vfmt): cc.FlexBuffer;
		initQuadIndices(idata);

		vDatas;
		uintVDatas;
		iDatas;
		meshCount: number;
		_infos;
		_flexBuffer;
	}
}

效果对比

测试案例

一个sprite,复制200次。分别使用默认的cc.Sprite和我们实现的NoColorSprite。

使用console.time函数结合cc.Director中的EVENT_BEFORE_UPDATE、EVENT_AFTER_UPDATE、EVENT_AFTER_DRAW事件统计前两百帧的游戏逻辑耗时及渲染耗时。

耗时对比如下:

绿色线为优化前,蓝色线为优化后。可以看出均有一定程度的减少。

render耗时由于前几帧较高,图表看起来比较奇怪,再贴一张去掉前三帧的对比图。

总结

简单来说,少了1/5的数据传输量,material中也不需要计算颜色,优化效果是可想而知的。

本优化并不适用于所有项目,由于颜色数据被去除了,透明度作为颜色值的其中一项,也不再生效了。图片本身的透明度会被保留,但无法再通过修改节点的透明度进行动态修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/444366.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】AttributeError: ‘list‘ object has no attribute ‘corr‘

一、问题描述 在绘制相关分析热力图的时候&#xff1a; import seaborn as sns to_corr [Age, Income, Kidhome, Teenhome, Recency, Complain, MntWines, MntFruits, MntMeatProducts, MntFishProducts, MntSweetProducts, MntGoldProds, NumDealsPurchases, AcceptedCmp1,…

如何将 Spire.Doc for C++ 集成到 C++ 程序中

Spire.Doc for C 是一个专业的 Word 库&#xff0c;供开发人员在任何类型的 C 应用程序中阅读、创建、编辑、比较和转换 Word 文档。 本文演示了如何以两种不同的方式将 Spire.Doc for C 集成到您的 C 应用程序中。 通过 NuGet 安装 Spire.Doc for C通过手动导入库安装 Spire.…

tomcat配置虚拟主机

文章目录 tomcat配置虚拟主机环境修改tomcat主配置文件server.xml配置配置虚拟主机目录以及文件重新启动tomcat修改windows的hosts文件浏览器测试 tomcat配置虚拟主机 环境 java version “1.8.0_261”Server version: Apache Tomcat/8.5.20 修改tomcat主配置文件server.xml…

缺省参数-函数重载

缺省参数 缺省参数是声明或定义函数时为函数的参数指定一个默认值 有什么用&#xff1f; 更加灵活的增加默认值&#xff0c;或者手动给一个初始值&#xff0c;解决了C语言#define给死一个值的缺陷&#xff0c;C语言无法做到缺省参数这么灵活 struct Stack {int* a;int top;in…

北邮22信通:(13)第三章 3.4 串的实现 KMP算法

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 上一篇文章&#xff1a; 下一篇文章&#xff1a; ***说明*** 1.本代码结合书上第二章线性表和4.3.3KMP算法结合书写。 2.加快匹配速度的根本原因&#xff1…

行业分析| 新的学习方式——在线自习室

互联网技术在快速革新中不断推动新应用、新场景、新模式和新业态的发展融通&#xff0c;如近年来不断催生的游戏直播、直播带货、户外直播等网络生态。随着互联网用户逐年增多&#xff0c;年轻化趋势明显&#xff0c;互联网直播内容逐渐向生活化、日常化拓展&#xff0c;加之“…

Linux 防火墙常用命令

目录 前文叙述 Linux 找不到 firewall 命令 firewalld 常用管理命令 firewall-cmd 常用命令参数说明 前文叙述 Linux 防火墙默认为开启状态&#xff0c;生产环境下 Linux 防火墙也肯定是开启状态。因此在生产环境下往往是开放特定端口让外部进行连接使用。 Linux 找不到 fir…

数字化时代,企业为什么越来越重视数据分析

自数据成为第五大生产要素后&#xff0c;其价值得到了越来越多企业的认可&#xff0c;也成为了各行各业企业的重要的资产。而信息化建设在企业中的发展更是给了数据增长的机会&#xff0c;随着业务信息系统在企业中成为基础建设&#xff0c;众多企业都通过业务系统沉淀了大量业…

JSP的基本使用总结

JSP的基本使用总结 &#x1f3e0;个人主页&#xff1a;shark-Gao &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是shark-Gao&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f389;目前状况&#xff1a;23届毕业生&#xff0c;目前在…

海睿思分享 | 风控监管,守住企业生命线

1 企业如何应对市场风险 随着市场形势日益严峻&#xff0c;企业风险系数也在同步增加&#xff0c;一旦风险管理出现重大问题&#xff0c;将是致命的、灾难性的&#xff0c;可能导致企业出现生存危机。 风控监管的主要目的在于通过对各类风险进行识别、分析、监控&#xff0c…

【java web篇】MyBatis之Mapper代理

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

MacOS版本RedisDesktopManager源码编译

1. 克隆 : git clone --recursive https://github.com/RedisInsight/RedisDesktopManager.git 查看依赖模块: git submodule 编译注意事件,部分源码的子仓库依赖没有下载完整的,要手动下载 brotli子模块 编译brotli子模块 $ mkdir out && cd out $ ../configure-c…

助力春耕:数智驱动现代农业高质量发展

最近有部很有意思的综艺《种地吧&#xff01;少年》&#xff0c;节目内容就是十个少年要用192天的时间在142亩土地上&#xff0c;完成抢收水稻&#xff0c;抢种小麦&#xff0c;并在6月份完成小麦的收割&#xff0c;这样一个内容。 这个节目没有流量明星&#xff0c;而被吸引去…

MyBatis(十六)MyBatis使用PageHelper

一、limit分页 mysql的limit后面两个数字&#xff1a; 第一个数字&#xff1a;startIndex&#xff08;起始下标。下标从0开始。&#xff09; 第二个数字&#xff1a;pageSize&#xff08;每页显示的记录条数&#xff09; 假设已知页码pageNum&#xff0c;还有每页显示的记录…

K8s集群搭建-Kubeadm方式搭建集群【1.23.0版本】

文章目录 一、初始化准备二、安装kubeadm三、初始化Master集群四、将新的Node节点加入集群五、部署CNI网络插件六、其他配置 Kubernetes1.24(包括1.24)之后不在兼容docker,如果有需要兼容docker的需求&#xff0c;则安装一个 cri-docker的插件&#xff0c;本文使用的是kuberne…

【技巧】如何在微信与企业微信端实现自动化ChatGPT智能机器人服务?(WorkTool)

场景描述 对于使用企业微信办公协作的公司/团体/组织等&#xff0c;在工作的时候&#xff0c;经常需要通过群机器人的方式&#xff0c;回答群内成员的问题。 基于此&#xff0c;一些企业想要将ChatGPT的智能对话能力与企业微信群机器人的回复能力结合&#xff0c;在企业微信群…

VMware Site Recovery Manager 8.7 (for vSphere 8 U1) - 数据中心灾难恢复 (DR)

请访问原文链接&#xff1a;https://sysin.org/blog/vmware-srm-8/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org Site Recovery Manager 8.7 | 18 APR 2023 | Build 21590800 什么是 Site Recovery Manager (SRM)&#xff1…

【网络安全】CVE漏洞分析以及复现

漏洞详情 Shiro 在路径控制的时候&#xff0c;未能对传入的 url 编码进行 decode 解码&#xff0c;导致攻击者可以绕过过滤器&#xff0c;访问被过滤的路径。 漏洞影响版本 Shiro 1.0.0-incubating 对应 Maven Repo 里面也有 【一一帮助安全学习&#xff0c;所有资源获取一…

GrapeCity Documents for Imaging

GrapeCity Documents for Imaging 现在可以使用高斯模糊效果在整个输入图像或部分图像上基于高斯函数创建模糊。 在GcBitmap类中添加了IsBlackAndWhite和IsGrayscale。这些方法可以更快地检查图像是由黑白像素组成还是仅由灰度组成。 IsBlackAndWhite方法检查所有图像像素是不透…

回炉重造八--系统启动和内核管理

系统启动和内核管理 1、系统启动 1.1 centos7启动的过程 UEFI或BIOS初始化&#xff0c;运行post开机自检选择启动的设备&#xff08;USB、硬盘、本地光盘&#xff09;引导装载程序&#xff0c;centos7是给grub2加载装载程序的配置文件&#xff1a; /etc/grub.d/ /etc/default…