excaliburjs / Excalibur

🎮 Your friendly TypeScript 2D game engine for the web 🗡️
https://excaliburjs.com
BSD 2-Clause "Simplified" License
1.73k stars 188 forks source link

Semi-transparent PNGs appear garbled #687

Closed hogart closed 7 years ago

hogart commented 7 years ago

Minimal code: http://codepen.io/hogart/pen/KNVNKB?editors=0010 On the left is image loaded through <img/>, on the right is excalibur's canvas. Image taken from ludum-dare-33 sample repo, where it was used as cursor. I tried several png images with similar problems.

Steps to Reproduce

Expected Result

Texture renders with semi-transparent areas

Actual Result

Texture looses semi-transparency, resulting in jagged edges and artifacts

Environment

eonarheim commented 7 years ago

@hogart Definitely looks like an issue, thanks for the codepen really easy to test :)

I tried setting game.setAntialiasing(true) in the codepen to no success.

I should have some free time this week to look into it more deeply. My first guess is that there is some loss of information between the PNG and the canvas, potentially a bug in our resource processing...

hogart commented 7 years ago

I narrowed it down to Sprite#_applyEffects, specifically to last line: this.internalImage.src = this._spriteCanvas.toDataURL('image/png');. But I've no idea what's the problem here, because .toDataURL support transparency given proper MIME-type.

hogart commented 7 years ago

Turns out it's rather connected with #481 and there's no loss of information. Flag Actor#_framesDirty is set in two cases, when we add new frames and when opacity changes. And if it's set, opacity effect is re-applied to every drawing in Actor#update. This leads to duplicate calls to Sprite#_applyEffects, so texture gets drawn twice. And that effectively kills opacity:)

hogart commented 7 years ago

Sorry for this, I was wrong. PR with fix for this follows.