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

Possible plan for tileset fallback handling #4448

Closed
GlyphGryph opened this issue Nov 17, 2013 · 5 comments

Comments

Projects
None yet
5 participants
@GlyphGryph
Copy link
Contributor

commented Nov 17, 2013

This primarily addresses issue where new content added to the game is untiled, but could also easily double as a method to easily create a new tileset from scratch without having to individually define anything.

This issue and the reasons for this sort of thing were most recently brought up by #4236 and the frustration other tileset makers have experienced trying to catch up and keep up with the addition of new content.

What we need is a capable (and editable) format for a high quality fallback system that can be used to dynamically tile new content, as it's added, without the need for creating new resources.

I've looked into it, and the only thing I can see working is something I brought up way back in the day when we first started. An index/icon pairing system.

It works like this:
We decide on a standard for png indexing - I think 8 colors should be enough. The index must be the same for every image, so it has to be decided in advance how many we'll use. We could implement it so that this only matter within-set though, and a later higher-color default could still be swapped in.
We define a pallet (indexed colour pairs), for each colour defined in-game.
We create an individual image for each ascii acharacter. The colours used here don't matter, though their indexes do.

Then we create an individual image for every ascii character using any colours (it doesn't matter which) so long as there's the right index of different colours or less.

When we come across an object that has no tile definition explicitly set to it, we read the color and symbol from the definition, grab the appropriate image and plug in the appropriate pallet. This will work, correctly, even for colour/symbol pairs that have never before existed in the game.

This can be changed by a tileset maker as part of their tileset, so if they wish they can have a customized look for "default" tiles. Our standard default should probably be a decent looking ascii-like.

PNGs do support indexing, so that wouldn't need to change.

This would also mean for many of the minimal tilesets, defining 16 color groups and 100 odd images would be the ONLY work the person would ever have to make - that's attractive, as a potential tileset designer!

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@JayThirtySeven

This comment has been minimized.

Copy link

commented Nov 18, 2013

I'm not too sure about the palette plan; why not just go through the pixels and recolor them? At each pixel you just calculate the brightness/luminosity then multiply the target color by the brightness value. Store the results on a new surface, as you obviously don't want to be doing this on the fly.

In my experience, palette swaps are not nearly as simple as they seem. Real palettes are so rarely used today that they tend to be more trouble than they're worth (especially from the artist's end of things.)

@Shadowdarke

This comment has been minimized.

Copy link

commented Nov 22, 2013

Performing luminosity calculations on each pixel is needlessly math intensive and somewhat limiting to the potential of the medium.

If the pixel is grayscale then the red, green, and blue components should equal one another and the result of the luminosity calculation would be the same value as any component value. I.E. if the pixel is mid level gray (#808080) then the standard luminosity calculation would yield (0.2126_128) + (0.7152_128) + (0.0722*128) = 128. To color this pixel red (#FF0000), you just multiple each component by 128/255 or 0.5 for a result of #800000. #808080 colored dark green (#8000) would give #4000.

However if you don't enforce grayscale and do the math component by component it provides more flexibility without complicating the math. redFinal = redTint * redOriginal / maxValue; greenFinal = greenTint * greenOriginal / maxValue; blueFinal = blueTint * blueOriginal / maxValue

Say the artist uses white (#FFFFFF) for the primary pixels in their font, but wants a red blood drip along the bottom edge. The edge pixels are #FF0000. Coloring it dark magenta #800080 would give #800080 pixels for the main body and #800000 for the edge. A dark red edge. using those same colors by luminosity only would yield simply a darker magenta (#1B001B) edge, because it would interpret the red as luminosity 54 (0.2126 * 255).

Coloring that same bloody edged letter blue (#0000FF) by component would leave a black edge, because the blue tint and the red base pixel have no components in common and they zero each other out. The same operation by luminosity would give a bright blue letter with a very dark blue edge (#00001B).

Yet another option instead of multiplying by component be to average by component.
redFinal = (redTint + redOriginal) / 2; greenFinal = (greenTint + greenOriginal) / 2; blueFinal = (blueTint + blueOriginal) / 2

In that case, the white letter with the red edge colored dark magenta would end up with main color #C080C0 and edge color #C00040. Coloring it blue produces main color #8080C0 and edge color #800080

I hope this graphic illustrates what I mean:
tinting

@GlyphGryph

This comment has been minimized.

Copy link
Contributor Author

commented Nov 22, 2013

Graphics already take too long to render. Indexing and pallet swapping is quick. It also allows for much higher quality work, because the artist actually has control over what will be rendered. Indexing is also fairly easy to do for an artist - it is literally pulldown menu -> index, save image and then edit pallete, save pallet.

The only other reasonable alternative is having them make every single combination individually, which is still better than the "automatic" system described above. It's just much larger and much slower than the indexed system (and a lot more work for the artist)

@JayThirtySeven

This comment has been minimized.

Copy link

commented Nov 23, 2013

@GlyphGryph You wouldn't want to do color transforms or palette swaps during play; with either system, you'll need to generate the alternate colors when the tileset is loaded. During the game, all tile rendering should be straight blits from one surface to another, so the method used to generate the tiles has no impact on performance.

As for how easy palettes are; it's generally bad to assume you know how easy something is across every image editor available. I'm in favor of standard 24/32bit RGB images because those are the default for nearly every modern editor I've encountered, while I've seen several with no useful concept of 8bit indexed color. Even if most major editors support it, the tools and terminology vary widely and most artists won't be familiar with the functionality.

@Shadowdarke I only suggested the luminosity test because that's a failry standard way of reliably recoloring any image without assuming/requiring it to be grayscale. If you think there's a use case for some other blend method I have no problem with that. My point was that it's not hard for the game to intelligently recolor an RGB image, so there's no reason to mess around with indexed colors.

@kevingranade

This comment has been minimized.

Copy link
Member

commented Jan 12, 2017

This hasn't been reported as a problem recently, it seems like the current fallback mechanisms are sufficient. If you're a tileset author and disagree, feel fre to repoen this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.