Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1410832 Posts in 69579 Topics- by 58571 Members - Latest Member: Experimagic

October 04, 2024, 08:09:40 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Sharpening textures in a 2D engine (openGL)
Pages: [1] 2
Print
Author Topic: Sharpening textures in a 2D engine (openGL)  (Read 6564 times)
Seiseki
Level 5
*****


Starmancer


View Profile WWW
« on: June 19, 2012, 06:49:49 AM »

I'm not a coder, but I do have some insight, albeit limited.

Now for the game we're developing, we're using openGL and quite large 2D textures that are scaled down.
Now the textures quickly loose their crispness when the game resizes them, with bilinear interpolation.
We're resizing to .25, .5 or .75 and never anything in between.
Using nearest would just make them too jaggy, so the only option left would be having a sharpening algorithm. Not in realtime, that would be silly.. But perhaps when the game loads and the assets are
adjusted for the current resolution.

Does this sound reasonable?
Does anyone have any experience with HD graphics in a 2D engine? Especially the part about adjusting for different resolutions.
Logged

Richard Kain
Level 10
*****



View Profile WWW
« Reply #1 on: June 19, 2012, 07:07:57 AM »

I've actually played around with this a bit myself, but I'm afraid I never found a solution. In the end, I just accepted the jaggies and moved on. I just don't think OpenGL is designed for scaling textures without some manner of interpolation. Adjusting anti-aliasing won't solve the problem. I'm thinking the solution you've already thought of is the best option. (having multiple-resolution versions of textures for different window resolutions)
Logged
ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #2 on: June 19, 2012, 07:16:05 AM »

Trilinear filtering (GL_LINEAR_MIPMAP_LINEAR) will probably look better than bilinear (GL_LINEAR).

Maybe a crazy idea: If you know you'll only ever be scaling to .25, .5, and .75, you could load a separate texture for each size. That way any sharpening or other adjustment could be done before the game even starts.
Logged

Seiseki
Level 5
*****


Starmancer


View Profile WWW
« Reply #3 on: June 19, 2012, 11:05:31 AM »

Yeah, well, we haven't really gotten the resolution scaling in yet which will dynamically scale everything, so it in the end it won't just be 0.5, 0.75 and 0.25, but it worries me when it even looks blurry with even sized numbers like 0.5.
Thinking about having a virtual resolution and basing everything upon that, to make sure the aspect ratios and sizes are maintained while the resolution changes.

We're also using mipmaps, so I guess it's trilinear.
Perhaps the game could sharpen the mipmaps when it loads in all the graphics assets.
Maybe I could look into that, I know source engine textures embed mipmaps in the texture files, so you can pre-sharpen them when you make the file.
Logged

Ludophonic
Level 2
**


View Profile
« Reply #4 on: June 19, 2012, 11:12:35 AM »

There are two options I can think of.

The first is to use pre-sharpened mipmaps as you mention. You can write a script in Photoshop to use it's internal scaling. Or perhaps download one (I think NVidia's photoshop tools come with one). If you're not using Photoshop you'll have to check if you have equivalent functionality available.

The second, more ambitious route is to look into signed-distance textures. Although they're usually used for magnification they can also help with minification.
Logged
Fallsburg
Level 10
*****


Fear the CircleCat


View Profile
« Reply #5 on: June 19, 2012, 11:42:59 AM »

Can you post a side by side of original texture and the scaled texture to show the loss of crispness?

Because I'm sort of at a loss for what you expect to have happen.  I mean, by scaling you are getting rid of information, and I would expect that this is always going to result in a loss of crispness. But since you are making it smaller, the loss of information shouldn't be a big problem since it is now smaller and therefore harder to see.
Logged
PompiPompi
Level 10
*****



View Profile WWW
« Reply #6 on: June 19, 2012, 01:15:35 PM »

The only sane way I can think of is having better mip maps. Mip maps are ment to give you better results when scaling down.
The "lazy" programmer's mip maps are simplly an average of several pixels into. Instead of producing the mip maps with average, you can produce them however you like(offline).
Heck you can even put a completly different image in each mip map level, if it somehow helps you.
But just to get the point.
Another thing(which you have in DirectX, but I assume also in OpenGL) is Antiscopic filter.
If you just resize a sprite, then it's of no use to you, but if you rotate or scale only the top of the sprite, then Antiscopic would make it sharper for non uniform defomrations.
That's all I can think of now.
Logged

Master of all trades.
rivon
Level 10
*****



View Profile
« Reply #7 on: June 19, 2012, 01:45:45 PM »

You probably mean Anisotropic filtering...
Logged
Ashaman73
Level 0
***



View Profile WWW
« Reply #8 on: June 19, 2012, 09:49:44 PM »

First off, as already mentioned, you should use mip-mapping and use a offline mipmapping generation tool to get better quality (i.e. gamma correction).

Then you should consider to improve the overall image quality with fullscreen post-processing shaders, this way you can use simple sharping algos (extrapolate with a blurred version), AA, HDR/Bloom, unsharp masking etc.
Logged

PsySal
Level 8
***


Yaay!


View Profile WWW
« Reply #9 on: June 19, 2012, 10:52:23 PM »

We're also using mipmaps, so I guess it's trilinear.

Try turning this off, and just using linear.

Remember that mipmaps add an extra layer of interpolation, depending on distance-to-camera. For a 2D game, you definitely don't want trilinear interpolation. Here's why:

Here's image 1, full resolution:
Code:
+----------+
|          |
|          |
|          |
|          |
+----------+
Here's image 2, half res:
Code:
+-----+
|     |
|     |
+-----+
What you want, based on screen resolution (or size of the polygon in pixels, let's say) is to use image 1, or use image 2, let's say.

The trouble with trilinear filtering, is that it will use something blended between image 1 and image 2. In 3D, this has the effect of avoiding a "pop" when objects change their texture mipmap as they move in and out of the camera range. However in 2D, since things never change their position in the camera range, you don't really want this.

The question remains whether or not you actually want to use mipmapping, at all. I suppose it depends on how your game works. If you for instance have a 1024x1024 explosion sprite, but sometimes that is scaled down very small, mipmapping may be worthwhile especially on slower hardware, if you have a lot of sprites. But really, you probably do not want to interpolate the mipmaps themselves.

Just my thoughts! I'm curious though, do you have any screenshots you can show the effect?
Logged
PsySal
Level 8
***


Yaay!


View Profile WWW
« Reply #10 on: June 19, 2012, 10:56:18 PM »

I was going to say, I also like the idea of using custom scaling when generating your lower-res textures, regardless of whether or not you use mipmapping per se.

But rather than use photoshop, what I would recommend is this-- do it in your own code, in-engine. Create your own algorithm to scale them down, maybe giving higher weight to certain colors that you deem more important, or whatnot. Bilinear interpolation is not hard, at all! But if you do it in your own code, maybe you can get a result that is tailored to your game.

More importantly, this saves you having to process things beforehand. Imagine when you get to the stage of producing a lot of graphics, if you have to run a script everytime you edit something!
Logged
bluescrn
Level 1
*


Unemployed Coder / Full-time Indie :)


View Profile WWW
« Reply #11 on: June 20, 2012, 12:05:59 AM »

What may help is a combination of:

1) Mipmaps
2) Trilinear filtering
3) Mipmap biasing

The mipmap bias (GL_TEXTURE_LOD_BIAS) is the important bit - it adjusts the scale at which the lower mipmaps will be used. Use a small negative bias (maybe -0.5f) to keep it using the large mipmaps for longer.

Don't make the bias too large, as you'll effectively be turning mipmaps off (and hurting performance)

Anisotropic filtering will *not* help for a 2D game.
Logged

Seiseki
Level 5
*****


Starmancer


View Profile WWW
« Reply #12 on: June 20, 2012, 09:21:40 AM »

Wow, this is very informational.
Especially the part about mipmaps. Thanks!

I'm gonna try disabling mipmaps and taking before/after screens.
And also doing a comparison with photoshops resizing results.
Logged

PsySal
Level 8
***


Yaay!


View Profile WWW
« Reply #13 on: June 23, 2012, 07:59:59 PM »

Post the results here! I'm really curious to see what the actual difference is....
Logged
Quarry
Level 10
*****


View Profile
« Reply #14 on: June 24, 2012, 01:59:52 AM »

GL_NEAREST?
Logged
_Tommo_
Level 8
***


frn frn frn


View Profile WWW
« Reply #15 on: June 24, 2012, 04:35:06 AM »

Protip: be sure that the rendered texels are correctly aligned to the screen pixels or OpenGL will mess up everything!

I had an ugly blur on any sharp edges in my images that I blamed on the scaling algorithm, BUT the png itself was just fine when viewed with Preview.
It turned out that when the level was scaled down to work at smaller resolutions, some sprites ended in floating point pixel positions... and that forced OpenGL to blur the pixels because of GL_BILINEAR.

For the scaling itself, it is much better to pre-scale everything in Photoshop and then use GL_NEAREST when drawing the actual sprites, as GL_BILINEAR _WILL_ mess any HD graphics for good.
I am using GL_NEAREST + bicubic sharper in PS + .5 and .25 reductions, and it works like a charm Beer!
Logged

Fallsburg
Level 10
*****


Fear the CircleCat


View Profile
« Reply #16 on: June 24, 2012, 06:20:44 AM »

GL_NEAREST?
Using nearest would just make them too jaggy
Logged
_Tommo_
Level 8
***


frn frn frn


View Profile WWW
« Reply #17 on: June 24, 2012, 07:05:04 AM »


GL_NEAREST means "OpenGL please leave my pixels unchanged if you can" which is precisely what you want with HD graphics.
If it's jagged, pre-scale it in PS and then make sure the sprite is pixel-aligned to the screen Smiley
Logged

Seiseki
Level 5
*****


Starmancer


View Profile WWW
« Reply #18 on: June 24, 2012, 01:02:13 PM »


GL_NEAREST means "OpenGL please leave my pixels unchanged if you can" which is precisely what you want with HD graphics.
If it's jagged, pre-scale it in PS and then make sure the sprite is pixel-aligned to the screen Smiley

I can't pre-scale it in PS if I want the game to support multiple resolutions..
Although if the game would scale the art assets and apply sharpening when it loads them I could use nearest neighbor for anything that isn't going to rotate.
Logged

_Tommo_
Level 8
***


frn frn frn


View Profile WWW
« Reply #19 on: June 24, 2012, 03:54:01 PM »

Mmh yep, rotating with GL_NEAREST is going to be very very jaggy, seems like you'll have to live with the bilinear then...
about the prescaling, in our game we're including 3 resolutions: one for the ipad3 and the pc, one for older ipads and retina iphones, and one for smaller screens.
We've chosen to have everything in the package because the other res are 1/4 and 1/16 big, (actually a bit more because jpg can efficiently compress uniform colors, but.) so it's doable.
It cuts on load times because smaller screens (on usually less powerful devices) load smaller files AND they don't have apply any scaling during loading.
Also it is easier on the ram: loading a 2048x1536 png on an ipod 3rd gen before scaling can trigger by itself a memory kill Smiley
Logged

Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic