pixijs / layers

Separate the z-hierarchy of your scene tree from its canonical structure.
https://pixijs.io/layers/docs/
MIT License
222 stars 57 forks source link

pixi-display + pixi-light Crash #25

Closed jonlepage closed 6 years ago

jonlepage commented 6 years ago

Hi ivan I have a small crash experimenting with pixi light and the layer system. I do not know if these my group system would cause this? I separated the process in 2 steps for easy debug.

Step1, the loader will inject resource in a global variable. at this step are all fine.

// ┌------------------------------------------------------------------------------┐
// PIXI LOADER for light ressources (testing)
//└------------------------------------------------------------------------------┘
_SLL.prototype.load_pixiLight = function() {
    const loader_light = new PIXI.loaders.Loader();
    loader_light.add('bg_diffuse', 'lightIMG/BGTextureTest.jpg')
        .add('bg_normal', 'lightIMG/BGTextureNORM.jpg')
        .add('block_diffuse', 'lightIMG/block.png')
        .add('block_normal', 'lightIMG/blockNormalMap.png');
    loader_light.load(onAssetsLoaded);

    function onAssetsLoaded(loader, res) {
        $SLL.resourceLight = { // add reference to $SLL global (debug only)
             bg:[res.bg_diffuse.texture, res.bg_normal.texture],
             block:[res.block_diffuse.texture, res.block_normal.texture],
             block1:[res.block_diffuse.texture, res.block_normal.texture],
             block2:[res.block_diffuse.texture, res.block_normal.texture]
        }
    };

    loader_light.onComplete.add(() => {$SLL.setLightLoaded()}); // tell the light loader are finish
};

step2 i initialise my layers system (original) and after inject light feature in the stage. the stage "this" are initialise before in other module. stage

Stage.prototype = Object.create(PIXI.display.Stage.prototype);
Stage.prototype.constructor = Stage;
Stage.prototype.initialize = function() {
    PIXI.display.Stage.call(this);
    this.interactive = false; // The interactive flag causes a memory leak.
};

step2 look at end on // PIXI LIGHT TEST IMPLEMENTATION

// LAYER ASIGNATION TO MAP STAGE
Spriteset_Map.prototype.createLowerLayer = function() {
    Spriteset_Base.prototype.createLowerLayer.call(this);
    // TODO: create global display.Group for avoid init each time new map loaded
    this.displayGroup = [
        new PIXI.display.Group(0, false), // backgroud Map. BG tile elements will no update and no interaction
        new PIXI.display.Group(1, true), // map elements default player, chara and all basic sprite update z and interaction
        new PIXI.display.Group(2, true), // map elements 2er
        new PIXI.display.Group(3, true), // map elements 3er
        new PIXI.display.Group(4, false), //levelGui: GUI Elements over maps
        new PIXI.display.Group(5, false), //levelMenu: MENU Elements over maps
        new PIXI.display.Group(6, false), //levelTxt: txt bubble, or SFX over all
    ];
    this.displayLayers = [];
    for (let l = 0, len = this.displayGroup.length; l < len; l++) {
        const DG = this.displayGroup[l];
        const DL = new PIXI.display.Layer(DG);
        this.displayLayers.push(DL);//(debugOnly) reference acces ref
        this.addChild(DL); // add to Stage PIXI.display
    };

    // PIXI LIGHT TEST IMPLEMENTATION
    var light = new PIXI.lights.PointLight(0xffffff, 1);
    this.addChild(new PIXI.display.Layer(PIXI.lights.diffuseGroup));
    this.addChild(new PIXI.display.Layer(PIXI.lights.normalGroup));
    this.addChild(new PIXI.display.Layer(PIXI.lights.lightGroup));
    // create ligth and normal
    function createPair(diffuseTex, normalTex) {
        var container = new PIXI.Container();
        var diffuseSprite = new PIXI.Sprite(diffuseTex);
        diffuseSprite.parentGroup = PIXI.lights.diffuseGroup;
        var normalSprite = new PIXI.Sprite(normalTex);
        normalSprite.parentGroup = PIXI.lights.normalGroup;
        container.addChild(diffuseSprite);
        container.addChild(normalSprite);
        return container;
    }

    let PAIR = {};
    for (const key in $SLL.resourceLight) {
        const res = $SLL.resourceLight[key];
        PAIR[key] = createPair(res[0], res[1]);
    }
    console.log('PAIR: ', PAIR); // add to stage
    this.addChild(PAIR.bg);
    this.addChild(PAIR.block);
    this.addChild(PAIR.block1);
    this.addChild(PAIR.block2);

    this.addChild(new PIXI.lights.AmbientLight(null, 0.4)); // GET ERROR !!!

    //... other stuff
};

at the line this.addChild(new PIXI.lights.AmbientLight(null, 0.4)); i get a error texLayer.getRenderTexture is not a function

image

if i remove this line, i can see all the element normal seem loaded. image

did you know what i'm doing wrong in my context ? i think it where and how i add light with new PIXI.display.Group? thank

jonlepage commented 6 years ago

ok a add i little hack to ytour plugin spine, see if(slot.attachment && slot.attachment.name.indexOf("_n")>-1){

       /* function Spine(spineData) {
            var _this = _super.call(this) || this;
            if (!spineData) {
                throw new Error('The spineData param is required.');
            }
            if ((typeof spineData) === "string") {
                throw new Error('spineData param cant be string. Please use spine.Spine.fromAtlas("YOUR_RESOURCE_NAME") from now on.');
            }
            _this.spineData = spineData;
            _this.skeleton = new pixi_spine.core.Skeleton(spineData);
            _this.skeleton.updateWorldTransform();
            _this.stateData = new pixi_spine.core.AnimationStateData(spineData);
            _this.state = new pixi_spine.core.AnimationState(_this.stateData);
            _this.slotContainers = [];
            _this.tempClipContainers = [];
            for (var i = 0, n = _this.skeleton.slots.length; i < n; i++) {
                var slot = _this.skeleton.slots[i];
                var attachment = slot.attachment;
                var slotContainer = _this.newContainer();
                */
                _this.slotContainers.push(slotContainer);
// check if the name have '_n', if yes it a normal, else a diffuse
                if(slot.attachment && slot.attachment.name.indexOf("_n")>-1){
                    slotContainer.parentGroup = PIXI.lights.normalGroup;
                }else{
                    slotContainer.parentGroup = PIXI.lights.diffuseGroup;
                }

I find it pretty easy to duplicate a slot and inject a normal. Ideally it would be to prepare the photoshop file so that it includes all the '_n' names. It's a little longer to update a file that was not have normal at the base. image

I will definitely wait for you to offer a more intelligent code I discussed it with dev from codeandweb, they tell me they will add new meta for detect more easy normal map with a atlas in next update.

jonlepage commented 6 years ago

a guy tell me a nice idea, attache a skin to say the current spine have a normal map. I need look this .

Edit: ok solved, i add this to your spine.js for now. I am going to wait for a more professional suggestion from you. For the moment it works well, what is important for allow me progress. The idea is simply to add a skin named "normal_n" when you work in SPINE2D sofware, that tell to your spine.js to add special extra parentgroup to slots and slots with "_n". I dont know about performance on this hack, but it make the workflow very easy. what do you think about this?

            var haveNormal = !!spineData.findSkin("normal_n") || false; // is have skin named Normal_n
            for (var i = 0, n = _this.skeleton.slots.length; i < n; i++) {
                var slot = _this.skeleton.slots[i];
                var attachment = slot.attachment;
                var slotContainer = _this.newContainer();
                _this.slotContainers.push(slotContainer);
               if(haveNormal){
                if(slot.attachment && slot.attachment.name.indexOf("_n")>-1){
                    slotContainer.parentGroup = PIXI.lights.normalGroup;
                    slotContainer.isNormal = true; //allow easy debug
                }else{
                    slotContainer.parentGroup = PIXI.lights.diffuseGroup;
                }
               };

image