Gamua / Starling-Framework

The Cross Platform Game Engine
http://www.starling-framework.org
Other
2.87k stars 826 forks source link

Ignore texture scale wthen create a BitmapFont #854

Closed ze0nni closed 8 years ago

ze0nni commented 8 years ago

Sometimes scale coordinates is bad idea. I heve no ideas how to fix it otherwise. Thanks.

badfont

goodfont

PrimaryFeather commented 8 years ago

Thanks a lot for the pull request!

Hm ... the question that should be asked, though, is why the scale factor of the texture is wrong? Since the font XML will always contain the data in pixels (not points), the BitmapFont class will take that into account, and for that it needs to use the scale factor.

How are you importing your texture that you can't give it the correct scale factor?

ze0nni commented 8 years ago

I am using StarlingBuilder and pack all textures and fonts-textures in to single atlas to reduce the number of draw calls. tp

I have several altases for different scalefactor 1x 2x 4x and only single json-file(StarlingBuilder) and single fnt-file. for any screen density. And after, i just scale rootSprite and load texture with different scale.

I understand that this is happening because I resize font-atlas, but downloading this atlas I pass correct scale and texture will transform coordinates to correct, not necessary recal them again.

Sorry for my english.

PrimaryFeather commented 8 years ago

In Starling 2, the Texture.fromBitmapData method got a new parameter, scaleModifier: Texture#fromTexture()

With the help of that method, you could "fix" the scale factor of any of the textures to the correct value. E.g. let's say you've got a texture that has a scale factor of 2 and want to change it to 1:

var texture_2x:Texture = ...; // scale factor 2
var texture_1x:Texture = Texture.fromTexture(texture_2x, null, null, false, 0.5); 

Note the 0.5 at the very end. This is multiplied by 2, thus you get a scale factor of 1. Could you use this to fix your issue?

I'd favor that solution, because if I add such a special parameter as you're suggesting to the BitmapFont, people might start asking to have this parameter at a whole lot of different places. With my solution, we'd work at the root of the problem instead — which I like better. :wink:

ze0nni commented 8 years ago

I think about this solution it will be more flexible. But chose faster way.

I tried to switch on the v2.0 and it work good. But I want use starling v1.8 until feathersUI v3.0.0 be in betta.

In this case I will extend SubTexture class from v1.8 bratch to this functional and make new pool-request or I switch to a branch v2.0 before =)

What do you think?

yuhengh commented 8 years ago

I would like to chime in here, for multiple texture scales, we are using the approach Daniel suggests. If using 1x texture, then use scaleFactor of 1. If using 2x texture, then use scaleFactor of 2. The editor can be always using 1x texture with scaleFactor of 1 (or 2x for scaleFactor of 2 if you prefer) This way using which set of texture is completely transparent to the game and you can use the same set of layouts for both. Let me know if you have any problems doing that. By the way I am glad to hear that you are using Starling Builder, please let me know when your game is live so I can have some community work to reference!

yuhengh commented 8 years ago

Hmm I think I have misunderstood your problem before. You are packing the same 1x font with 1x, 2x, 4x atlas, and need to remedy for the non-1 scaleFactor atlas right? Looks like Texture.fromTexture is a good choice.

PrimaryFeather commented 8 years ago

Thanks for chiming in, Johann!

Yes, we could probably port this back to Starling 1.8 — however, you could also give version 2.0 a try. If it's easy to port to the new version, that's probably preferable, because most of the ongoing development will happen on that branch.

Just give it a try and then let me know. :smile:

ze0nni commented 8 years ago

Hmm. It is still work wrong =/

new BitmapFont(
    Texture.fromTexture(uiAtlas.getTexture(fontName), null, null, false, 42),
    fntData);

I can create subTexture with scale 42 and get texture with scale = 21 after BitmapFont divided font coordinates by 21, and I take the same result.

May me pass scaleModifier into BitmapFont constructor?

new BitmapFont(
    uiAtlas.getTexture(fontName),
    fntData
    2);

It will solve the problem make solution more flexible. Or I can manual transform fntData =\

ze0nni commented 8 years ago

Hm it happens with TextureAtlas to (I am about transormation coordinates). I think it just TextureMatrix modify after current texture changed, but atlas always use original coordinates without scale.

It does not create problems but I It felt wrong.

I do not studied the source code deeply. Correct me I say is wrong.

PrimaryFeather commented 8 years ago

You know what, could you create a quick sample, complete with source code and font atlas? That would be ideal; I'm sure we can make this work. Thanks in advance!

ze0nni commented 8 years ago

@PrimaryFeather here https://github.com/ze0nni/StarlingFontScale

PrimaryFeather commented 8 years ago

Perfect, thanks! I'll look into it and will get back to you a little later this week.

PrimaryFeather commented 8 years ago

Okay, I just had time to look into this!

You're right, the font XML is currently always processed with pixel values, so it would need a property like the one you suggested to fix this. However: it's not a good idea to do so.

The thing is: if you work with two scale factors, you should always export your font two times: once with scale factor 1 (say: font size = 12) and once with scale factor 2 (say: font size = 24). Anything else will lead to artifacts and aliasing issues.

That's because the font export relies on integer pixels. For example, your glyphs will probably be placed with a margin of one pixel. If you load that font with only half the resolution, that one pixel will suddenly be just 0.5, which means that you'll see neighboring glyphs at the borders of each glyph. Granted, if you set the margin to 2, that might be fixed; but then you waste a lot of texture memory. And what happens if you need to support scale factor 3 or 2.5?

And the margin is not the only problem: on scaling down, some of your glyphs might end up on a non-integer position (e.g. before: x=5, after: x=2.5), which will make them appear blurry. To avoid that, you'd have to make your bitmap font creation software places your glyphs only at multiples of 2. Which, if you find such a software, will waste even more texture memory.

Do you see what I mean? :wink:

Thus, it's always recommended to always create one font XML and texture per scale factor.

ze0nni commented 8 years ago

Right I use margin = 4 and have not problems with scaled text. Characters with non-integer position really can be dangerous. May be you right. I would not want complicate my atlas-pack script, but if you think it preferred way I choose it. Thanks!

PrimaryFeather commented 8 years ago

Yeah, I know it's painful to use different bitmap font textures for each atlas scale factor. But in the long run, it will definitely avoid problems.

Thanks for your understanding! 😄