Pixelated graphics

edited July 2013 in Help request
Hi,

I'm trying to make a pixelated "old fashion" game. I want graphics to be pixelated but can't achieve it.

As zooming/scaling in ORX is all blurry, I assume it's not using GL_NEAREST scale method (not that it is what I'm looking for).

Here is what I need. I have 16x16px image scaled up to 64x64px. But I want that 64x64px rendered image use only 16x16 squares so it looks like rendered with low resolution.

I know there are some tricky ways how to achieve this in OpenGL (something like rendering scene in half size, grabbing that result and rendering it all scaled up), but is there a way to achieve this in ORX?

Comments

  • jimjim
    edited July 2013
    There is Smoothing property in config. Set it to true if you want pixelated effect. You can use it in three places.

    1. In Display template, if you want your whole game to have pixelated. By default, its value is false. Hence, no pixelated effect, when you zoom in/out a sprite.

    2. In your Object template, if you want some of your objects to have pixel effect. By default, it would use Smoothing defined in Display template.

    3. In your Graphic template, if you want some of your graphic to be pixelated. By default, it would use Smoothing defined by its Object.

    Now, use it according to your need.

    Cheers !
  • edited July 2013
    Thats not what I needed. It's still too smooth. Scaling method still counts missing points.

    I want it to have visible squares like on left side of this picture.
    Diamond_anti-aliasing_demo.png

    This picture has only 16x16px originally, rendered to bigger size and still is smooth.
    Screen%20shot%202013-07-31%20at%206.17.32%20PM.png
  • jimjim
    edited July 2013
    If your actual image is not pixel friendly then I am afraid, the solution is a bit complex. Can you show me your actual image ? if you image contains blurred pixel or anti-aliased pixel, then its would be very hard what you are trying to achieve. Look at this image, its pixel friendly, because is has sharp edge and no semi-transparent pixel when you open it with any image editing software.
    soldier.png

    You have to make your images like this, otherwise, drawing a smaller version onto a texture and resizing it wont do what you want. I know nothing about shaders, but you can look into alpha testing to discard semi-transparent pixel or any alternative to alpha testing if you are targeting mobile.
  • edited July 2013
    Well, as far as I know this image should be pixel friendly too. IMO problem is in way OpenGL renders it.

    char_small.png
  • jimjim
    edited July 2013
    Now, I know what your problem is, its normally found when you try to rotate a pixelated line or a line drawn with nearest filtering. But for lines, you can apply other techniques to smoothen it, but for image its quite impossible to avoid this effect. Its more visible when you are applying nearest filtering. Its not only opengl, its also a problem in flash.

    So, a good solution to this problem is, if you have rotated sprite in your pixel game, don't rotate the sprite, but use a sprite-sheet, make your rotation an animation, this way you you are in total control to draw your sprite in certain rotation. This is quite easy and result is as expected as you want. This is the only easy solution I can see now. I have seen many developers to apply this techniques to avoid this type of problem.
  • edited July 2013
    Well if I get you right, you're suggesting doing it "manually" with pictures? This sounds way too laborious, doing dozen images for simple rotation. Maybe time to try basics like SDL and see how it will work.

    But thanks for your answers!
  • jimjim
    edited July 2013
    I have seen many library and engines including unity, cocos2d, libgdx, flash, this is present every where. It has nothing to do with opengl or any other rendering techniques. If you have long edge in your image and you are using sharp or nearest filtering, this is bound to happened while rotation. The way I see, I have failed to specify this problem technically to you. Best of luck with SDL. Btw, they have released SDL 2.0, and its awesome. Its worth your try.
  • jimjim
    edited July 2013
    If it helps you can check this link, the author faced similar problem like yours, though he did not find an absolute fix, there is a photoshop trick mentioned here, you can try it if all fails. And its without pre-rotated sprite,
    http://www.cocos2d-iphone.org/forums/topic/how-to-get-smooth-edge-when-rotating-sprite/
  • edited July 2013
    Well he faced opposite problem. He wanted his edges to be smooth, I want edges to have visible pixels.
  • jimjim
    edited July 2013
    can you give me link to a game where you have seen the kind of effect your are looking for ?
  • edited July 2013
    For example Teleglitch
  • jimjim
    edited July 2013
    As I can see, they have used shading techniques and their border is very crisp. And the smallest sprite I can see in their is 60x80 pixel long. Pixel art does not mean, you make an image 16x16 and scale it and use it in your game. Rather, they draw it the way, it seems the image is scaled, in reality its not.
  • edited July 2013
    Hi there!

    Wow already 13 posts, I'm coming a bit late on that one, sorry! :)

    So yes, you want a pixelated effect, the good news is that it's pretty easy, the bad news is that it depends on which version of orx you are using.

    Let me explain myself: I can see two main ways of achieving this effect: either by doing some compositing as you suggested in your first post (rendering to a low res target and then upscaling the result to screen without smoothing, ie. GL_NEAREST) or by using a custom shader.

    The custom shader option is the most flexible one as you can easily control different parameters or even warp the "grid" on which the pixels look to be aligned. You can also adapt the effect at runtime to change the level of pixelation (I think lydesik's using that on the title screen of his latest game).
    However it's also a bit more tricky to put together than simply doing compositing.

    Compositing is pretty simple: you create a texture in memory that has a lower resolution, link it to the viewport that renders your scene, and then reuse that texture on an object that will then be displayed on screen.
    There's actually a tutorial on that: http://orx-project.org/wiki/en/orx/tutorials/community/iarwain/compositing

    Now, if you're using a very recent version of orx (synced since last week), the whole compositing process has been simplified. Unfortunately I'm still at the hotel with no real internet connection and haven't been able to update the tutorial yet.
    If you choose to go down the compositing road, let me know and I'll try to write a quick example very soon.

    Jim: Thanks a lot for all the support you've been giving on the forum lately, it's really nice to see the efforts you make to liven the place! :D
  • edited July 2013
    I quickly hacked something in config using my playground (Bounce, if you're familiar with orx's sources) and I got that in a matter of minutes (ignore the console display which is not affected by the compositing :D):
    screenshot_0001.png

    Are you after something similar to this?
  • jimjim
    edited August 2013
    This is a way to get pixelated effect but this technique was not present 10-15 years ago, but pixel games where there so how they achieved pixel effect ? Because their art was pixelated, they used shading, dithering and other techniques to make pixel effect. Stretching a 8x8 image to 128x128 is not pixel art imho. But this is cool technique if you want your normal sprite to look pixelated dynamically. For example, you want in your game that, player can switch between pixel world and normal world, then this is the technique. But if you are looking into real pixel effect then I am afraid you would get it work but it would look bad and its not real pixel art.

    I would have been regular here but I had classes in the past as I am done with my undergrad, I have plenty of time at night, coz I have a day job and I am currently in my workplace :)
  • edited August 2013
    Iarwain: thanks! I That looks exactly what I was looking for. I will try techniques you've explained and let you know.

    Jim: I never really talked about pixel art as I know this technique is all handwork and thus time consuming. I wanted only pixelated "low-res" effect. And it looks like I can get it working with ORX :)
  • edited August 2013
    Great!
    The compositing as explained in the tutorial will still work with the latest version, it's simply that it is now simpler to do it, but it's optional.

    Mainly the intermediate texture doesn't have to be created in code anymore and there's no need for an object in the second scene that renders to screen. I'll post a quick example tonight as I'm on my phone at the moment.
  • edited August 2013
    Thanks! I'll get latest version and wait so I don't have to do it twice.
  • jimjim
    edited August 2013
    Jim: I never really talked about pixel art as I know this technique is all handwork and thus time consuming. I wanted only pixelated "low-res" effect. And it looks like I can get it working with ORX

    My bad, but the link you gave me confused me. Anyway, doing something old fashioned with advanced opengl techniques is not old fashioned anymore :p Good luck with your game.
  • jimjim
    edited August 2013
    Btw, I am also waiting for a more simplified version of compositing as many other cool effects can be done easily using it like breaking the whole game screen like glass, making a smooth non-pixelated scene into a pixelated scene gradually and other things mainly related to scene transition.
  • edited August 2013
    ... Anyway, doing something old fashioned with advanced opengl techniques is not old fashioned anymore :p

    Yea, that's why I used quotation marks :)
  • edited August 2013
    So let's see (doing it in the forum editor so hopefully I won't make any mistakes :))...

    In config:
    [Display]
    ScreenWidth = 1024
    ScreenHeight = 768
    ; That's our target resolution, but it doesn't really matter
    Smoothing = false; Let's use GL_NEAREST by default, otherwise compositing will look blurry
    
    [RenderViewport]
    BackgroundColor = (0, 0, 0); Better to define a background (ie. clear) color, helps some hardware with optimization
    Size = (256, 192, 0); Here we define our viewport size, which in turn will define the texture size
    ; We set it low-res so that, with our display target resolution, each pixel will look 4x4
    Texture = RenderTexture; Pick whichever name you want as long as it's not an existing file on disk :)
    Camera = ...; Use your regular game camera here
    
    [ScreenViewport]
    BackgroundColor = (0, 0, 0)
    ShaderList = @; Hey, we're using a shader to do the compositing, also we don't need a camera as we're not rendering a scene :)
    Code = "void main()
    {
      // Simply copy the pixel from texture
      gl_FragColor = texture2D(texture, gl_TexCoord[0].xy);
    }"
    ParamList = texture
    texture = RenderTexture; It's here that we link the texture used as input for our shader to the one used as target when rendering our scene with RenderViewport, so make sure to use the same name as previously :)
    
    [Game]
    ViewportList = RenderViewport # ScreenViewport; Let's go data-driven all the way down!
    

    That's all for config, let's look at the code (really there isn't much).
    orxSTATUS orxFASTCALL Init()
    {
      orxU32 i;
    
      // Pushes Game section
      orxConfig_PushSection("Game");
    
      for(i = 0; i < orxConfig_GetListCounter("ViewportList"); i++)
      {
        // Creates viewport
        orxViewport_CreateFromConfig(orxConfig_GetListString("ViewportList", i));
      }
    
      // Pops config section
      orxConfig_PopSection();
    }
    

    There you go, you have your two viewports (just make sure the one that creates the intermediate texture is created before the one that's going to use it in its shader ;)).

    The way it works is that when a viewport is created and has a target texture, it'll try to load it from file (or cache if it's already loaded). If the texture's not found, it'll then create a new texture (and own it and delete it when needed) using its current size. If the viewport has no size set, it'll use the screen size instead.

    Lastly, the last viewport doesn't render a scene (no camera) so there's no real CPU rendering cost there, however, as it's linked to a shader, it'll render a quad to its target using that shader.

    Of course you can add more complexity with more viewports + intermediate textures for lighting or other effects, but in that case everything should be controllable from config, as long as all the viewports are created code-wise, you're good. :)

    If I didn't make any mistakes, that's all you need to setup compositing for your game.

    Lemme know if you have any troubles or any thoughts/comments!

    Cheers,

    Rom
  • edited August 2013
    Thanks for your explanation.

    I have just little problem building new version. I can't get working Lua premake script and building with old Makefile isn't working (ORX can't load plugins).
  • jimjim
    edited August 2013
    Premake was needed to customized a bit to build orx, so if you get it from other place it wont work, to build orx you need to get premake4.exe located in extern/premake/ folder, search for the premake.exe in 'premake' folder, as I don't remember the exact path and I am out of home right now.
  • edited August 2013
    Thanks!
  • jimjim
    edited August 2013
    Wow, just tried it and it works like a charm, its really cool. Thanks kenn, to bring up this topic, its a really cool effect :) and thanks to iarwain to put up a quick tutorial and its amazing how powerful orx can be. Hail Orx !

    3S1TE.jpg

    Btw, I am getting an error or warning don't know,
    [23:41:30] [RENDER] [orxRender.c:orxRender_Home_RenderViewport():2105] Not a val
    id camera.
    

    All I did, just added the config part into 01_object.ini, and changed 'RenderViewport' Camera to 'Camera' what was defined in config. Here is my config, http://codepad.org/2NTS0XmK
  • jimjim
    edited August 2013
    Okay, the warning message is removed in the latest, ignore it.
  • jimjim
    edited August 2013
    one more thing, how do I access the texture I am drawing on from code, so that I could change its size hence effect the amount of pixelation.
  • edited August 2013
    Sorry for the long delay, we only got internet setup tonight! :)

    If you want to access the texture, you can either retrieve it from the viewport (orxViewport_GetTextureList()) or directly with its name (orxTexture_CreateFromFile). Yes, that name is a bit misleading now, I know. :/

    If you retrieve it with the CreateFromFile function, don't forget to delete it when you're done (it just updates internal reference counters).

    When you have the texture, get the bitmap from it, unlink it, delete it, create a new one and link it to the texture using the same name.

    After that, don't forget to update the size of the viewport as it won't match the new texture.

    But as this is quite a lot of things to do just in order to change the pixelation size, you could simply play with the shader instead. :)

    Create the texture as big as needed for the less pixelated version (might even be the exact size of your screen), and then control the size of the visible "pixel" via a parameter in your shader. You can modify that value on the fly by listening to the shader param event.
    This approach is also more efficient as there won't be any de-allocation/re-allocation of textures.
Sign In or Register to comment.