Skip to content

UIPerformance


WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

ts
import { BoundingBox, Color, Engine3D, GUIConfig, Object3D, Scene3D, UIImage, TextAnchor, UITextField, Vector2, Vector3, ViewPanel, clamp, KelvinUtil, AtmosphericComponent, CameraUtil, HoverCameraController, View3D, DirectLight } from "@orillusion/core";
import {Stats} from "@orillusion/stats";
import dat from "dat.gui";

class SpriteSheet {
    public static toggleMove: boolean = false;
    public static toggleAnim: boolean = true;

    private img: UIImage;
    private lastIndex: number = -1;
    private frame: number = 100 * Math.random();
    private frameSpeed: number = 0.5 + Math.random();
    private frameCount = 13;
    private keyFrames: string[];
    private moveSpeed: Vector2;
    private bound: BoundingBox;

    constructor(img: UIImage, keyFrames: string[], bound: BoundingBox) {
        this.img = img;
        this.bound = bound;
        this.keyFrames = keyFrames;
        this.moveSpeed = new Vector2(Math.random() - 0.5, Math.random() - 0.5);
    }

    updateFrame(): void {
        if (SpriteSheet.toggleAnim) {
            this.frame += this.frameSpeed;
            let newIndex = Math.floor(this.frame * 0.1) % this.frameCount;
            if (newIndex != this.lastIndex) {
                this.lastIndex = newIndex;
                this.img.sprite = Engine3D.res.getGUISprite(this.keyFrames[newIndex]);
            }
        }

        if (SpriteSheet.toggleMove) {
            let x = this.img.uiTransform.x;
            let y = this.img.uiTransform.y;
            x += this.moveSpeed.x;
            y += this.moveSpeed.y;
            if (x < this.bound.min.x || x > this.bound.max.x) {
                this.moveSpeed.x *= -1;
            }
            if (y < this.bound.min.y || y > this.bound.max.y) {
                this.moveSpeed.y *= -1;
            }

            this.img.uiTransform.setXY(x, y);
        }

    }
}

class Sample_UISpriteSheet {
    spriteSheets: SpriteSheet[];
    text: UITextField;
    scene: Scene3D;
    keyFrames: string[];

    async run() {
        Engine3D.setting.shadow.autoUpdate = true;

        GUIConfig.quadMaxCountForView = 5001;
        await Engine3D.init({
            renderLoop: () => {
                this.renderUpdate();
            }
        });

        this.spriteSheets = [];
        this.keyFrames = [];
        let frameStart = 65;//65~77

        for (let i = 0; i < 13; i++) {
            this.keyFrames.push((frameStart + i).toString().padStart(5, '0'));
        }

        // init Scene3D
        this.scene = new Scene3D()
        this.scene.exposure = 1
        this.scene.addComponent(Stats)

        // init sky
        let atmosphericSky: AtmosphericComponent
        atmosphericSky = this.scene.addComponent(AtmosphericComponent)

        // init Camera3D
        let camera = CameraUtil.createCamera3DObject(this.scene)
        camera.perspective(60, Engine3D.aspect, 1, 5000)

        // init Camera Controller
        let hoverCtrl = camera.object3D.addComponent(HoverCameraController)
        hoverCtrl.setCamera(-30, -15, 100)

        // init View3D
        let view = new View3D()
        view.scene = this.scene
        view.camera = camera

        // create direction light
        let lightObj3D = new Object3D()
        lightObj3D.x = 0
        lightObj3D.y = 30
        lightObj3D.z = -40
        lightObj3D.rotationX = 20
        lightObj3D.rotationY = 160
        lightObj3D.rotationZ = 0

        let light = lightObj3D.addComponent(DirectLight)
        light.lightColor = KelvinUtil.color_temperature_to_rgb(5355)
        light.castShadow = true
        light.intensity = 30

        this.scene.addChild(light.object3D)

        // relative light to sky
        atmosphericSky.relativeTransform = light.transform

        Engine3D.startRenderView(view)

        await Engine3D.res.loadAtlas('https://cdn.orillusion.com/atlas/Sheet_atlas.json');
        await Engine3D.res.loadFont('https://cdn.orillusion.com/fnt/0.fnt');

        this.text = this.createText();

        let gui = new dat.GUI()
        let dir = gui.addFolder('Orillusion')
        dir.open()
        dir.add(SpriteSheet, 'toggleMove');
        dir.add(SpriteSheet, 'toggleAnim');

        let button = {
            'add': () => {
                if (this.spriteSheets.length < 99999) {
                    this.addLotOfSprite();
                }
            }
        }
        dir.add(button, 'add')
        this.addLotOfSprite();
    }

    addLotOfSprite() {
        // enable ui canvas at index 0
        let canvas = this.scene.view.enableUICanvas(0);
        //create UI root
        let panelRoot: Object3D = new Object3D();
        //create panel
        let panel = panelRoot.addComponent(ViewPanel);
        canvas.addChild(panel.object3D);
        //create sprite sheet list
        this.createSpriteSheets(panelRoot);
    }

    createText(): UITextField {
        let canvas = this.scene.view.enableUICanvas(0);
        //create UI root
        let panelRoot: Object3D = new Object3D();
        //create panel
        let panel = panelRoot.addComponent(ViewPanel);
        panel.panelOrder = 10000;
        canvas.addChild(panel.object3D);
        let textQuad = new Object3D();
        panelRoot.addChild(textQuad);
        let text = textQuad.addComponent(UITextField);
        text.uiTransform.resize(400, 60);

        text.fontSize = 24;
        text.alignment = TextAnchor.MiddleCenter;

        return text;

    }


    private createSpriteSheets(root: Object3D) {
        let width = Engine3D.width;
        let height = Engine3D.height;
        let bound = new BoundingBox(new Vector3(0, 0, 0), new Vector3(width, height));
        //color
        let color: Color = Color.random();
        color.a = 1;
        color.r = clamp(color.r * 1.5, 0.5, 1);
        color.g = clamp(color.g * 1.5, 0.5, 1);
        color.b = clamp(color.b * 1.5, 0.5, 1);

        let size = 64
        for (let i = 0; i < 5000; i++) {
            let quad = new Object3D();
            root.addChild(quad);
            let img = quad.addComponent(UIImage);
            img.color = color;
            img.sprite = Engine3D.res.getGUISprite('00065');
            img.uiTransform.resize(size, size);
            img.uiTransform.x = (Math.random() - 0.5) * width;
            img.uiTransform.y = (Math.random() - 0.5) * height;
            let sheet: SpriteSheet = new SpriteSheet(img, this.keyFrames, bound);
            this.spriteSheets.push(sheet);
        }

        this.text.text = this.spriteSheets.length.toString() + ' Sprites';
    }

    renderUpdate() {
        for (const item of this.spriteSheets) {
            item.updateFrame();
        }
    }

}

new Sample_UISpriteSheet().run();