Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

The image below shows two sprites rendered with point sampling on top of a background:

enter image description here

  • The left skull has no rotation/scaling applied to it, so every pixel matches perfectly with the background.
  • The right skull is rotated/scaled, and this results in larger pixels that are no longer axis aligned.

How could I develop a pixel shader that would render the transformed sprite on the right with axis aligned pixels of the same size as the rest of the scene?

This might be related to how sprite scaling was implemented in old games such as Monkey Island, because that's the effect I'm trying to achieve, but with rotation added.


Edit

As per kaoD's suggestions, I tried to address the problem as a post-process. The easiest approach was to render to a separate render target first (downsampled to match the desired pixel size) and then upscale it when rendering a second time. It did address my requirements above.

First I tried doing it Linear -> Point and the result was this:

enter image description here

There's no distortion but the result looks blurred and it loses most of the highlights colors. In my opinion it breaks the retro look I needed.

The second time I tried Point -> Point and the result was this:

enter image description here

Despite the distortion, I think that might be good enough for my needs, although it does look better as a still image than in motion.

To demonstrate, here's a video of the effect, although YouTube filtered the pixels out of it:

http://youtu.be/hqokk58KFmI

However, I'll leave the question open for a few more days in case someone comes up with a better sampling solution that maintains the crisp look while decreasing the amount of distortion when moving.

share|improve this question
    
That's supposed to be a skull...? –  DeadMG Apr 7 '12 at 15:48
    
@DeadMG An ox skull, I guess? –  David Gouveia Apr 7 '12 at 15:54
    
Nice effect, looks better than I thought it'd look (I tried it on EXTREMELY low res and palette, 40x30 EGA.) That's pretty much the look you'll get making your own postfx shader. BTW, I doubt there's a better sampling solution that keeps the effect as you intend. NN is pretty much what gives that crisp look, any other sampling will blur the final image (just guessing anyways.) –  kaoD Apr 7 '12 at 16:45
    
@kaoD But remember that I'm applying two passes. The second pass which upsamples the image will still be nearest neighbor to preserve the retro feel. But I think there might be some benefit in trying different sampling techniques for the first pass. I'm currently looking into Scale2x! –  David Gouveia Apr 7 '12 at 17:00
    
@kaoD Nah, I give up. Changing shader parameters between each sprite call with SpriteBatch requires me to use Immediate mode, so it's not worth the trouble. I'll go with this :) –  David Gouveia Apr 7 '12 at 18:07

1 Answer 1

up vote 3 down vote accepted

You should apply your shader AFTER your sprite has been rotated.

If the whole scene has not been shaded yet and your sprites are actually pixelated, what you need is some kind of post-FX filter for your whole scene. Averaging regions of pixels will work ok. It's not exactly what you intend (it'll look kinda dithered when moving/rotating) but it might do the trick.

The only way to keep that retro look truthful to what you want is to actually draw your sprite rotations yourself. It has nothing to do with how scaling was implemented: the resolution was actually poor, speaking of which, did you try with extremely low resolutions? It might also do the trick and will look more natural since, well, it's actually what caused the effect you're looking after. And it's cheap! VERY cheap! In fact it'll be cheaper than what you already have (less fragment shader executions.)

The effect is ruined in your sample image because your resolution is high compared to your sprites, so it lets you see the real pixels on the scene.

share|improve this answer
    
Yes, I'm not using any shaders yet. It's just regular sprites with very low resolution textures, rendered with XNA's default SpriteBatch with point sampling turned on. But a post-fx might really work out. For starters, I'll try rendering with linear sampling to a render target, and then render the entire render target to the backbuffer with point sampling. –  David Gouveia Apr 7 '12 at 15:06
    
@DavidGouveia don't miss the opportunity of undergrading your resolution. If you really want to achieve the original effect it's your best shot. If you need your high resolution (if a portion of your GFX is hi-res or you want to match native resolutions) you can still render to a low-res off-screen buffer and then paint it in your high resolution framebuffer as a full-screen quad with filtering turned off. Keep in mind you need to match aspect ratios to avoid rectangular pixels, of course. –  kaoD Apr 7 '12 at 15:08
    
Check my edit :) I think it solved most of the problem, although I'm still curious if there is a better sampling solution that nearest neighbor for this problem. I'll let the question run for a while longer. –  David Gouveia Apr 7 '12 at 15:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.