Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: Fragment shader for game tile engine (tilemap) smooth scrolling/per-pixel offset fail

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    10

    Fragment shader for game tile engine (tilemap) smooth scrolling/per-pixel offset fail

    Okay, tile_types_super_texture is a row of several 16x16 tile type textures, which are the tile types. Then according to tilemap_pixels, which is a 1-tile-per-pixel representation of the visible map on screen. According to the value within the red channel, it would be that index towards the end. Think of the super texture as a linear array, where each element is 16x16 pixels big, and the red channel is the index to the element.

    This worked wonderfully, but it only scrolled to every 16x16 tile, so scrolling was jumpy and not per-pixel/smooth scrolling. So I thought I would do m_viewPosition & TILE_SIZE-1, which gives me the remaining pixels which cannot align to the 16x16 grid.

    However, as you can see below, where I added the - int (offset.x), and .y, instead of smoothly scrolling, it's actually creating a sort of window blinds shutter effect, where if i move..say..8 pixels (half a tile) out, many tiles are cut in half (oddly..not all of them).

    Does this have to do with using texelFetch? I was thinking about resorting back to texture2D, so that I can run on lower end hardware as well. Or am I doing something intrinsically incorrect?

    Code :
    #version 130
    //unsupported though, isn't it? #extension GL_EXT_gpu_shader4 : enable
     
    // for a 1600x900 screen, this results in an image of 50x100 with each pixel representing a tile
    uniform sampler2D tilemap_pixels;
     
    // a runtime generated spritesheet of all tiles we know, each tile being 16x16 (so 48x16 if there are 3 tile types)
    uniform sampler2D tile_types_super_texture;
     
    // offset (remainder of view coordinates versus tile size). to achieve per-pixel smooth scrolling
    uniform vec2 offset;
     
    //FIXME: stop hardcoding ..
    ivec2 TILE_SIZE = ivec2(16, 16);
     
    void main()
    {
        ivec2 tilemap_size = textureSize(tile_types_super_texture, 0);
     
        ivec2 screen_coordinates = ivec2(gl_FragCoord.x, gl_FragCoord.y);
     
        // find the pixel (RGBA) values in the tilemap pixel representation that is what we're
        // currently interested in.
        vec4 currentPixel = texelFetch(tilemap_pixels, screen_coordinates / TILE_SIZE, 0);
     
        ivec2 tileCoordinate;
        tileCoordinate.x = (int(currentPixel.r * 255.0) ) * TILE_SIZE.x + (screen_coordinates.x % TILE_SIZE.x) - int(offset.x);
        tileCoordinate.y = screen_coordinates.y % TILE_SIZE.y - int(offset.y);
     
        vec4 tileColor = texelFetch(tile_types_super_texture, tileCoordinate, 0);
     
        gl_FragColor = tileColor;
    }

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,098
    I don't think this is right

    Code :
     
    vec4 currentPixel = texelFetch(tilemap_pixels, screen_coordinates / TILE_SIZE, 0);

    This implies that the first 16 pixels on the screen are all from the first tile - this is only true if offset.x = 0

  3. #3
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    10
    Quote Originally Posted by tonyo_au View Post
    I don't think this is right

    Code :
     
    vec4 currentPixel = texelFetch(tilemap_pixels, screen_coordinates / TILE_SIZE, 0);

    This implies that the first 16 pixels on the screen are all from the first tile - this is only true if offset.x = 0
    oh wow, you're absolutely right. I didn't need the other offset, I just needed it in that. I didn't think that would work, since there are just 1 pixels there which represent 1 tile.. interesting.

    updated and working wonderfully code. thanks a bunch

    Code :
    #version 130
    //unsupported though, isn't it? #extension GL_EXT_gpu_shader4 : enable
     
    // for a 1600x900 screen, this results in an image of 50x100 with each pixel representing a tile
    uniform sampler2D tilemap_pixels;
     
    // a runtime generated spritesheet of all tiles we know, each tile being 16x16 (so 48x16 if there are 3 tile types)
    uniform sampler2D tile_types_super_texture;
     
    // offset (remainder of view coordinates versus tile size). to achieve per-pixel smooth scrolling
    uniform vec2 offset;
     
    //FIXME: stop hardcoding ..
    ivec2 TILE_SIZE = ivec2(16, 16);
     
    void main()
    {
        ivec2 tilemap_size = textureSize(tile_types_super_texture, 0);
     
        ivec2 screen_coordinates = ivec2(gl_FragCoord.x + int (offset.x), gl_FragCoord.y - int (offset.y));
     
        // find the pixel (RGBA) values in the tilemap pixel representation that is what we're
        // currently interested in.
        vec4 currentPixel = texelFetch(tilemap_pixels, screen_coordinates / TILE_SIZE, 0);
     
        ivec2 tileCoordinate;
        tileCoordinate.x = (int(currentPixel.r * 255.0) ) * TILE_SIZE.x + (screen_coordinates.x % TILE_SIZE.x);// - int(offset.x);
        tileCoordinate.y = screen_coordinates.y % TILE_SIZE.y;// - int(offset.y);
     
        vec4 tileColor = texelFetch(tile_types_super_texture, tileCoordinate, 0);
     
        gl_FragColor = tileColor;
    }

  4. #4
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    10
    ah yes, i encountered another issue and fixed it easier than i thought..

    on the app side, I just passed it a column and row 1 bigger to the pixel map..that way that will take care of borders. so x was fixed, but the bottom of the screen had a gap that was horrid and distracting since it moved. Turns out i had to offset screen coordinates by a TILE_SIZE

    Code :
    #version 130
    //unsupported though, isn't it? #extension GL_EXT_gpu_shader4 : enable
     
    // for a 1600x900 screen, this results in an image of 50x100 with each pixel representing a tile
    uniform sampler2D tilemap_pixels;
     
    // a runtime generated spritesheet of all tiles we know, each tile being 16x16 (so 48x16 if there are 3 tile types)
    uniform sampler2D tile_types_super_texture;
     
    // offset (remainder of view coordinates versus tile size). to achieve per-pixel smooth scrolling
    uniform vec2 offset;
     
    //FIXME: stop hardcoding ..
    ivec2 TILE_SIZE = ivec2(16, 16);
     
    void main()
    {
        ivec2 tilemap_size = textureSize(tile_types_super_texture, 0);
     
        ivec2 screen_coordinates = ivec2(gl_FragCoord.x + int(offset.x), gl_FragCoord.y - int(offset.y) + TILE_SIZE.y);
     
        // find the pixel (RGBA) values in the tilemap pixel representation that is what we're
        // currently interested in.
        vec4 currentPixel = texelFetch(tilemap_pixels, screen_coordinates / TILE_SIZE, 0);
     
        ivec2 tileCoordinate;
        tileCoordinate.x = (int(currentPixel.r * 255.0) ) * TILE_SIZE.x + (screen_coordinates.x % TILE_SIZE.x);
        tileCoordinate.y = (screen_coordinates.y) % TILE_SIZE.y;
     
        vec4 tileColor = texelFetch(tile_types_super_texture, tileCoordinate, 0);
     
        gl_FragColor = tileColor;
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •