Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue regarding loading normal maps with spritesheets #6491

Closed
dreasgrech opened this issue May 4, 2023 · 14 comments
Closed

Issue regarding loading normal maps with spritesheets #6491

dreasgrech opened this issue May 4, 2023 · 14 comments

Comments

@dreasgrech
Copy link

Version

  • Phaser Version: Phaser 3.6.0
  • Operating system: Windows 10
  • Browser: Google Chrome v.112.0.5615.138 (64bit)

Description

Encountered an issue where sometimes, most noticeably in unfavorable network conditions, when loading a normal map image for a spritesheet, the normal map image doesn't fully load.

Example Test Code

The issue was first observed in one of the fellow Discord member's project where the frames of a spritesheet were not being loaded. We confirmed this with the following code:

preload()
{
    window.savedThis = this;

    // Adding a filecomplete hook so that we can look at the loaded frames
    this.load.on(`filecomplete-spritesheet-${pt.Tiles}`, function (key, type, data) {
        console.log("finished loading", key, type, data, savedThis.textures.get(pt.Tiles).frames);
    });

    this.load.spritesheet({
        key: pt.Tiles,
        url: "assets/main-tileset/breakout-extruded.png",
        normalMap: "assets/main-tileset/breakout-extruded_n.png",
        frameConfig: {
            frameWidth: 16,
            frameHeight: 16,
            spacing: 2,
            margin: 1,
            startFrame: 0,
            endFrame: 99
        }
    })

    ...
}

When loading the page normally, all of the 100 frames were correctly being logged to the console. But in intermittent cases, we were receiving the log that there aren't any frames in .frames

This was later confirmed when looking at the following online example: https://labs.phaser.io/edit.html?src=src/game%20objects/lights/sprite%20sheet%20light.js

When I disabled caching and set the network emulation to 3G in Chrome' dev tools, I got these warnings in the online normal example:

image

Additional Information

Network emulation and disabling caching is done from Chrome Dev tools:

image

@samme
Copy link
Contributor

samme commented May 5, 2023

The problem is that when the normal map loads second, it adds itself to the cache as a single-frame image.

@PaulB-H
Copy link

PaulB-H commented May 11, 2023

Okay, I haven't been able to figure out how to edit the files correctly to test... but it must have something to do with a1e77e9 since that's where this functionality was added?

I noticed there is a situation in SpriteSheetFile.js where the order the files are passed to this.cache.addSpriteSheet() change, could this be causing it?

//  We do, but has it loaded?
if (linkFile.state >= CONST.FILE_COMPLETE)
{
    //  Both files have loaded
    if (this.type === 'normalMap')
    {
        //  linkFile.data = Image
        //  this.data = Normal Map
       this.cache.addSpriteSheet(this.key, linkFile.data, this.config, this.data);
    }
    else
    {
        //  linkFile.data = Normal Map
        //  this.data = Image
        this.cache.addSpriteSheet(this.key, this.data, this.config, linkFile.data);
    }
}

@samme
Copy link
Contributor

samme commented May 11, 2023

The problem is in ImageFile’s addToCache method, when it’s a normal map and it loads after the linked SpritesheetFile.

Changing to

linkedFile.addToCache()

seems to fix it.

@PaulBellow
Copy link

Having a similar problem, I think. Every once in a while, it glitches and shows the entire spritesheet rather than the slices for the tiles.

linkedFile.addToCache()

Where to change? Or is a fix in the works?

Thanks.

@PaulB-H
Copy link

PaulB-H commented Jul 26, 2023

Samme referenced a potential fix in the engine, I wasn't able to figure it out how to implement it myself when I looked a few months ago.

I changed back to the "old" way to load normal maps.

this.load.image("spritesheet-normal", "assets/spritesheet-normal.png");

this.load.spritesheet("spritesheet", "assets/spritesheet.png", {
  frameWidth: 16,
  frameHeight: 16,
  margin: 1,
  spacing: 2,
});

this.load.once("complete", function (loader: Phaser.Loader.LoaderPlugin) {
  const sheet = loader.textureManager.get("spritesheet");
  const normalMap = loader.textureManager.get("spritesheet-normal");
  const normalMapSrcImg = normalMap.getSourceImage();

  if (
    normalMapSrcImg instanceof HTMLImageElement ||
    normalMapSrcImg instanceof HTMLCanvasElement
  ) {
    sheet.setDataSource(normalMapSrcImg);
  }
});

Wish I could figure out how to fix the issue with the engine.

@PaulBellow
Copy link

Thanks. It's so weird that it's so occasional in nature. Props to the OP who figured out why it might be happening.

With the "old way," I can then add.sprite and have the normal maps attached? It's just not as clean?

Appreciate the comment/code.

I'm new to Phaser - developing a roguelike hooked up to ChatGPT...

@PaulB-H
Copy link

PaulB-H commented Jul 26, 2023

Yeah, doing it that way does still "attach" the normal map to the sprite-sheet, so any sprite referenced will already have the normal map ready for the lighting pipeline.

However, even this way I have noticed a couple times the normal map loaded as the main sprite image (resulting in a very trippy looking map) so there might be another issue still, if you implement it this way and experience that too please mention it!

@PaulBellow
Copy link

Thanks. I'll give it a try.

It's like 1 out of 100 tries... but random...and, yeah, very trippy haha...

I love the lighting effect, but I need stability for my upcoming soft launch...

I wonder if size has something to do with it? I'm around 75k or so here...

After trying the "old" method, I'll report back and take a screenshot if it happens again.

Knowing how to change the core code for "linkedFile.addToCache()" (or that a fix is coming) would be helpful, though.

Thanks again.

@PaulB-H
Copy link

PaulB-H commented Jul 31, 2023

Updating from 3.55 to 3.6 seems to have resolved the issue where the normal map loads as the spritesheet image, so if you haven't, definitely try that

@PaulBellow
Copy link

I'm on 3.6 and it's still happening, though infrequently... :/

@PaulB-H
Copy link

PaulB-H commented Aug 1, 2023

Are you loading it as the code example I posted above?

With that method I haven't had the missing frames nor psychedelic episodes.

@PaulBellow
Copy link

Oops. Sorry, no. I've been hunting other bugs. Still have the newer / easier method with 3.6.0.

I'll get the loader way plugged in then report back if it's still happening. Thanks again.

@PaulBellow
Copy link

Are you loading it as the code example I posted above?

With that method I haven't had the missing frames nor psychedelic episodes.

Don't want to jinx it, but so far so good with loading the long method. Thanks again!

@photonstorm
Copy link
Collaborator

Thank you for submitting this issue. We have fixed this and the fix has been pushed to the master branch. It will be part of the next release. If you get time to build and test it for yourself we would appreciate that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants