欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

抖抖fps抖up,Stage和StageGL性能测试

程序员文章站 2024-03-16 21:16:04
...

StageGL更新公告 STAGEGL – A FASTER, BETTER, STRONGER WEBGL UPDATE TO EASELJS
参考 CreateJs - EaselJs 文档

概述

2017年4月,EaselJs发布更新,正式推出了StageGL

Stage一样,StageGL也是加载显示列表的根级别容器,直接继承于Container。同时是 WebGL-optimized

所以 StageStageGL 到底有多大差别呢?
“抖” 个简单的试验!


形单影只的“抖”

随便从网上找了一张像素小人图(如存在版权问题,还请告知…)
抖抖fps抖up,Stage和StageGL性能测试
做成了SpriteSheet图
抖抖fps抖up,Stage和StageGL性能测试
然后让他在canvas中“抖”起来
抖抖fps抖up,Stage和StageGL性能测试
此处用的 Stage,帧频基本保持在 60 fps 无压力
只不过诺大的画布上,“他”好寂寞…

核心代码

// function init()
// 构建舞台 & 加载图片
stage = new createjs.Stage("examCanvas")
loader = new createjs.LoadQueue(false)
loader.addEventListener('complete', handleComplete)
loader.loadManifest(
    [{
        src: 'mansheet.png', id: 'man'
    }],
    true, '../_assets/img/')
// function handleComplete()
// 创建sprite动画
let spriteSheet = new createjs.SpriteSheet({
    'images': [loader.getResult('man')],
    'frames': { 'width': 160, 'height': 280, 'count': 2, 'regX': 80, 'regY': 140 },
    'animations': {
        'play': [0, 1, 'play', 0.5]
    }
})

let man = new createjs.Sprite(spriteSheet, 'play')
man.setTransform(Math.random() * 960, Math.random() * 400, 0.1, 0.1)
stage.addChild(man)

createjs.Ticker.timingMode = createjs.Ticker.RAF
createjs.Ticker.addEventListener("tick", tick)
// function tick()
// 随时间变化获取fps & 刷新stage
let fps = Math.round(createjs.Ticker.getMeasuredFPS())
stage.update()

来5000个一块“抖”

将代码中构建 Sprite 实例 man 的区域循环 5000

就变成了大家一起来high的样子,好温(膈)暖(应)????
抖抖fps抖up,Stage和StageGL性能测试
此时独显的风扇开始狂吹…
同时,fps 徘徊在 30 左右,小人们的动作变慢了????

核心代码

for (let i = 0; i < 5000; i++) {
    let man = new createjs.Sprite(spriteSheet, 'play')
    man.setTransform(Math.random() * 960, Math.random() * 400, 0.1, 0.1)
    stage.addChild(man)
}

StageGL出场,平滑且安静的“抖”

抖抖fps抖up,Stage和StageGL性能测试
只需要做小小的调整,fps 就再次重回高地,且风扇也不转了????

不过你发现没有
画布上的 fps 标签没有了

核心代码

// stage = new createjs.Stage("examCanvas")
stage = new createjs.StageGL("examCanvas")

对比调整

按官方的说法,StageGL 可以充分利用GPU在优化内容
但这其实这只是 StageStageGL 最基本的区别

官方给出的 StageGL 显著特点

  • Intelligent batching, with multiple textures in a batch, using the full number available on your hardware
  • 智能批处理,每批次处理多种纹理,利用全部可用硬件
  • No restrictions on display list order
  • 显示列表顺序无限制
  • Automatic GPU memory management
  • 自动GPU内存管理
  • Full cache support
  • 全缓存支持
  • Full filter support
  • 全过滤器支持
  • Canvas 2D Stage fallback
  • 在不支持WebGL的设备上,自动呈现Canvas 2D Stage

StageGL 的使用限制

  • ShapeShadowText 均不会显示
  • 想要显示上述无法渲染的内容,需要通过 cache 缓存
  • 图像会被包装成 WebGL 的纹理,每个图形卡的并发纹理有限制,过多的纹理会明显降低性能
  • 每个 cache 都算作一个单独的纹理。建议使用 SpriteSheetSpriteSheetBuilder 来减少纹理数量
  • 在多个 StageGL 实例间使用图像节点(DOM Image/Canvas Element),必须是一个 clone
  • 如果在创建StageGL实例后调整画布大小,必须调用 updateViewport
  • 最佳性能将来自手动管理纹理内存,但默认情况下会自动处理

因此,针对 StageGLShapeText 不显示的问题,只需要调整几句代码即可

核心代码

// function handleComplete()
// 在定义完shape和text后,进行cache
fpsLabel.cache(0, 0, 960, 400)
fpsBack.cache(0, 0, 960, 400)

// function tick()
// 随时间变化,同时还要updateCache
fpsLabel.updateCache()

完整代码

Github - Performance

<!-- PerformanceGL.html -->
<!DOCTYPE html>
<html lang="en">

<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">
    <title>EaselJS: Performance</title>

    <link href="../_assets/css/shared.css" rel="stylesheet" type="text/css" />

    <script src="../lib/easeljs-NEXT.js"></script>
    <script src="../lib/preloadjs-NEXT.min.js"></script>

    <script>
        let stage, loader, fpsLabel

        function init() {
            // 利用StageGL实现
            stage = new createjs.StageGL("examCanvas")

            loader = new createjs.LoadQueue(false)
            loader.addEventListener('complete', handleComplete)
            loader.loadManifest(
                [{
                    src: 'mansheet.png', id: 'man'
                }],
                true, '../_assets/img/')
        }

        function handleComplete() {
            let spriteSheet = new createjs.SpriteSheet({
                'images': [loader.getResult('man')],
                'frames': { 'width': 160, 'height': 280, 'count': 2, 'regX': 80, 'regY': 140 },
                'animations': {
                    'play': [0, 1, 'play', 0.5]
                }
            })

            for (let i = 0; i < 5000; i++) {
                let man = new createjs.Sprite(spriteSheet, 'play')
                man.setTransform(Math.random() * 960, Math.random() * 400, 0.1, 0.1)
                stage.addChild(man)
            }

            fpsLabel = new createjs.Text("@ -- fps", "bold 20px Arial", "#000");
            fpsBack = new createjs.Shape(
                new createjs.Graphics().beginFill('#fff').drawRect(0, 0, 100, 20)
            )

            fpsLabel.cache(0, 0, 960, 400)
            fpsBack.cache(0, 0, 960, 400)

            fpsLabel.x = fpsBack.x = 10;
            fpsLabel.y = fpsBack.y = 20;

            stage.addChild(fpsBack, fpsLabel)

            createjs.Ticker.timingMode = createjs.Ticker.RAF
            createjs.Ticker.addEventListener("tick", tick)
        }

        function tick() {
            let fps = Math.round(createjs.Ticker.getMeasuredFPS())
            fpsLabel.text = ` @ ${fps} fps`
            fpsLabel.updateCache()
            stage.update()            
        }

    </script>
</head>

<body onload="init()">
    <header class="Nora7aki">
        <h1>性能测试 performace</h1>

        <p>
            通过<code>StageGL</code>渲染的5000个动画
        </p>
    </header>

    <div class="content" style="overflow: hidden;width: 960px;height: 400px">
        <canvas id="examCanvas" width="960" height="400"></canvas>
    </div>
</body>

</html>
<!-- PerformanceGL.html -->
<!DOCTYPE html>
<html lang="en">

<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">
    <title>EaselJS: Performance</title>

    <link href="../_assets/css/shared.css" rel="stylesheet" type="text/css" />

    <script src="../lib/easeljs-NEXT.js"></script>
    <script src="../lib/preloadjs-NEXT.min.js"></script>

    <script>
        let stage, loader, fpsLabel

        function init() {
            // 利用Stage实现
            stage = new createjs.Stage("examCanvas")

            loader = new createjs.LoadQueue(false)
            loader.addEventListener('complete', handleComplete)
            loader.loadManifest(
                [{
                    src: 'mansheet.png', id: 'man'
                }],
                true, '../_assets/img/')
        }

        function handleComplete() {
            let spriteSheet = new createjs.SpriteSheet({
                'images': [loader.getResult('man')],
                'frames': { 'width': 160, 'height': 280, 'count': 2, 'regX': 80, 'regY': 140 },
                'animations': {
                    'play': [0, 1, 'play', 0.5]
                }
            })

            for (let i = 0; i < 5000; i++) {
                let man = new createjs.Sprite(spriteSheet, 'play')
                man.setTransform(Math.random() * 960, Math.random() * 400, 0.1, 0.1)
                stage.addChild(man)
            }

            fpsLabel = new createjs.Text("@ -- fps", "bold 20px Arial", "#000");
            fpsBack = new createjs.Shape(
                new createjs.Graphics().beginFill('#fff').drawRect(0, 0, 100, 20)
            )

            stage.addChild(fpsBack, fpsLabel);
            fpsLabel.x = fpsBack.x = 10;
            fpsLabel.y = fpsBack.y = 20;

            createjs.Ticker.timingMode = createjs.Ticker.RAF
            createjs.Ticker.addEventListener("tick", tick)
        }

        function tick() {
            let fps = Math.round(createjs.Ticker.getMeasuredFPS())
            fpsLabel.text = ` @ ${fps} fps`
            stage.update()            
        }

    </script>
</head>

<body onload="init()">
    <header class="Nora7aki">
        <h1>性能测试 performace</h1>

        <p>
            通过<code>Stage</code>渲染的5000个动画
        </p>
    </header>

    <div class="content" style="overflow: hidden;width: 960px;height: 400px">
        <canvas id="examCanvas" width="960" height="400"></canvas>
    </div>
</body>

</html>

码字不易,如果喜欢,不用三连,点个赞????便是最大的鼓励
欢迎关注微信公众号 "书咖里的曼基康"
抖抖fps抖up,Stage和StageGL性能测试