Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: How to get the seams out of tiled zooming?

  1. #1
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    How to get the seams out of tiled zooming?

    In one of my latest projects, I'm having some difficulty trying to get large tiles to zoom in and out, yet stay next to one another without a noticeable seam.

    At first I thought it had to do with lack of precision, then I noticed some 'glitchy-ness' with the floating point values I was using. Then I got curious and I tried to flat out overlap them on purpose. What I found out blew my mind. There was a black seam even though it should have in theory just be the texture overlapped over the other.

    So what am I doing or not doing wrong here?

    I am using OpenGL in Ortho mode, and here is my function that I use to do this...

    [pascal]procedure DrawMap_Seamless(X, Y, SrcWidth, SrcHeight, DestWidth, DestHeight: Real; Texture: TTexture);
    var
    texX, texY : Real;
    begin
    glEnable(GL_TEXTURE_2D); //Enable Texturing
    glBindTexture(GL_TEXTURE_2D, Texture.ID); //Bind Texture

    glDisable(GL_BLEND);
    glEnable(GL_ALPHA_TEST); //Enable Alpha (Transparency) (Uses Texture Alpha channel)
    glAlphaFunc(GL_GREATER, 0.1); //Set Alpha settings

    glColor3f(1, 1, 1); //Make sure color is white (Normal)

    BeginOrtho; //Switch to 2D mode
    glPushMatrix; //Save Current Matrix
    glTranslatef(X, Y, 0); //Move to Objects location

    texX := SrcWidth / Texture.Width;
    texY := SrcHeight / Texture.Height;

    glBegin(GL_QUADS);
    glTexCoord2f(0, 0);
    glVertex2f(0, 0);

    glTexCoord2f(texX, 0);
    glVertex2f(DestWidth, 0);

    glTexCoord2f(texX, texY);
    glVertex2f(DestWidth, DestHeight);

    glTexCoord2f(0, texY);
    glVertex2f(0, DestHeight);
    glEnd;

    glPopMatrix; //Reload Old Matrix
    EndOrtho;
    end;
    [/pascal]

    Now here is the code I use to draw my wonderful (2048x2048 32-bit png imported texture) map...

    [pascal] // Draw Map
    if (ScreenX <ScreenWidth> MapWidth - ScreenWidth / MapZoom / 2) then
    DrawMap_Seamless((-ScreenX * MapZoom + (MapTex[0].Width * MapZoom) + (MapTex[1].Width * MapZoom)) + ScreenWidth / 2,
    (-ScreenY * MapZoom) + ScreenHeight / 2,
    MapTex[0].Width, MapTex[0].Height,
    (MapTex[0].Width * MapZoom),
    (MapTex[0].Height * MapZoom),
    MapTex[0]);[/pascal]

    ScreenX, ScreenY are the map scroll position offsets.
    MapTex[] is obviously my array of TTexture objects (just the 2; 0 and 1) TTexture.ID is where I store the GL texture number.
    MapZoom is obviously the current zoom size that I'm currently using.

    So how do I get rid of this annoying black seam?

    I can post a demo if it's needed.
    Jason McMillen
    Pascal Game Development
    Co-Founder





  2. #2

    How to get the seams out of tiled zooming?

    Try playing with the glTexEnv settings, try adjusting the clamping to GL_CLAMP, GL_CLAMP_TO_EDGE and GL_REPEAT to see if it makes any difference. Also if you clamp the edges try using instead of 0.0 and 1.0 something like 0.001 and 0.999 as texture coordinates, this way the edges should be filtered smoothly.
    If you develop an idiot proof system, the nature develops better idiots.

  3. #3
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    How to get the seams out of tiled zooming?

    Looking up more about GL_CLAMP and GL_CLAMP_TO_EDGE, I have come across this glTexParameter. It doesn't seem to do a very good job of explaining the difference between GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T.

    What is the difference, why would I use one or the other and what would you recommend?

    Please note that this is the first time playing around with textures in this manner so some added explanations would help greatly, thanks!
    Jason McMillen
    Pascal Game Development
    Co-Founder





  4. #4
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    How to get the seams out of tiled zooming?

    It seems that my 2nd block of code is missing the 3 other function calls. :?


    ...the missing code...
    [pascal] DrawMap_Seamless((-ScreenX * MapZoom) + ScreenWidth / 2,
    (-ScreenY * MapZoom) + ScreenHeight / 2,
    MapTex[0].Width, MapTex[0].Height,
    (MapTex[0].Width * MapZoom),
    (MapTex[0].Height * MapZoom),
    MapTex[0]);
    DrawMap_Seamless((-ScreenX * MapZoom + (MapTex[0].Width * MapZoom)) + ScreenWidth / 2,
    (-ScreenY * MapZoom) + ScreenHeight / 2,
    MapTex[1].Width, MapTex[1].Height,
    (MapTex[1].Width * MapZoom),
    (MapTex[1].Height * MapZoom),
    MapTex[1]);
    if (ScreenX > MapWidth - ScreenWidth / MapZoom / 2) then
    DrawMap_Seamless((-ScreenX * MapZoom + (MapTex[0].Width * MapZoom) + (MapTex[1].Width * MapZoom)) + ScreenWidth / 2,
    (-ScreenY * MapZoom) + ScreenHeight / 2,
    MapTex[0].Width, MapTex[0].Height,
    (MapTex[0].Width * MapZoom),
    (MapTex[0].Height * MapZoom),
    MapTex[0]);[/pascal]
    Jason McMillen
    Pascal Game Development
    Co-Founder





  5. #5

    How to get the seams out of tiled zooming?

    About glTexParameteri/f...

    It controls the texture coordinate wrapping. In this case the target is always GL_TEXTURE_2D and parameters GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T.

    WRAP_S is the s coordinate or "x", if you like and WRAP_T is the t coordinate ie. "y" for the textures. The coordinates start from bottom left (s:0, t:0) and go to top right (s:1, t:1).

    Setting the WRAP parameters control how the texture edges are handled, GL_CLAMP clamps the coordinates between 0 and 1, but depending on filtering, mip map levels and such there might be visible seams between adjacent polygons.

    GL_CLAMP_TO_EDGE is pretty much the same, but it filters the edges better and usually there's no visible seams. Use this for example on skyboxes to avoid seams on the cube faces.

    GL_REPEAT repeats the texture coordinates, if you set the coordinates outside the range of (0,1) they are interpolated and this causes the texture to repeat over and over again on the polygon. This is useful for walls, floors and such that has repeating pattern.

    Try experimenting with these parameters and use different values for texture coordinates to see what they do. Just draw a single quad on the screen and see what happens.

    You should definitely have a look at Red Book, it's a bit outdated but it covers the basic stuff and is still a good reference for beginners.
    If you develop an idiot proof system, the nature develops better idiots.

  6. #6
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    How to get the seams out of tiled zooming?

    Ok I figured out the specifics thanks you your help. However it seems that it doesn't quite help much with regards to the problem. :?


    So... I've uploaded a copy of the executable and source so you can see and point out what stupid thing I'm doing.

    EDIT: I had to re-upload it... doing that now... Done! Here it is.

    I've left the GraphicsUnit.pas function with the debugging code in so you can see what I'm trying to do to see why I'm not able to 'overlap' these dame textures to eliminate the black line.

    I've tried clamping to get rid of any artifact that might be showing on the edge and I've also tried to overlap the two textures to prevent a small gap by messy floating point values. Neither seem to be working. :roll:

    Look for the function 'DrawMap_Seamless' and the function calls I make in the main project source file. I'm either calculating something wrong or I'm not setting something properly.

    GL_CLAMP_TO_EDGE does not exist in the gl.pas version that is included with the version of JEDI-SDL I'm using btw! :doh:
    Jason McMillen
    Pascal Game Development
    Co-Founder





  7. #7

    How to get the seams out of tiled zooming?

    Quote Originally Posted by WILL
    So... I've uploaded a copy of the executable and source so you can see and point out what stupid thing I'm doing.
    I'm having a bit of problems on getting Lazarus working and compiling your program...

    Look for the function 'DrawMap_Seamless' and the function calls I make in the main project source file. I'm either calculating something wrong or I'm not setting something properly.
    Couldn't spot anything obviously wrong in there...

    GL_CLAMP_TO_EDGE does not exist in the gl.pas version that is included with the version of JEDI-SDL I'm using btw! :doh:
    In SDL you have to load the OpenGL_1_2 extension, like this: glext_LoadExtension('GL_version_1_2') in your OpenGL initialization.

    I did a quick test in my planet renderer with the two different wrap settings. Ignore the black triangles, they're caused by a bug in my edge splitting code.

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);


    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


    As you can see there's quite a difference on how the edges are filtered. I think that GL_CLAMP_TO_EDGE will fix your problem.
    If you develop an idiot proof system, the nature develops better idiots.

  8. #8
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    How to get the seams out of tiled zooming?

    Ok makes sense. I found where GL_CLAMP_TO_EDGE is located in the JEDI-SDL source. However there is another problem with the damn thing. Namely the glext.pas unit supplied with JEDI-SDL.

    Quote Originally Posted by vgo
    In SDL you have to load the OpenGL_1_2 extension, like this: glext_LoadExtension('GL_version_1_2') in your OpenGL initialization.
    This is the part that I'm stuck on. For some reason glext.pas freaks out on line 3790 giving me a SIGSEGV (memory) error.

    Is there some kind of library file I need to pull this off?

    Here is the function that dies on me...
    [pascal]function Load_GL_version_1_2: Boolean;
    {var
    extstring : PChar;}
    begin

    Result := FALSE;
    //extstring := glGetString( GL_EXTENSIONS );

    @glCopyTexSubImage3D := SDL_GL_GetProcAddress('glCopyTexSubImage3D'); // <-- This is the line!
    if not Assigned(glCopyTexSubImage3D) then Exit;
    @glDrawRangeElements := SDL_GL_GetProcAddress('glDrawRangeElements');
    if not Assigned(glDrawRangeElements) then Exit;
    @glTexImage3D := SDL_GL_GetProcAddress('glTexImage3D');
    if not Assigned(glTexImage3D) then Exit;
    @glTexSubImage3D := SDL_GL_GetProcAddress('glTexSubImage3D');
    if not Assigned(glTexSubImage3D) then Exit;

    Result := TRUE;

    end;[/pascal]

    I should also note that I'm using JEDI-SDL 1.0 BETA 1. Any ideas? :?
    Jason McMillen
    Pascal Game Development
    Co-Founder





  9. #9

    How to get the seams out of tiled zooming?

    Sounds like SDL_GL_GetProcAddress has not been initialized and that's why it screws up things. I have no idea why it's not initialized, though.

    Your SDL initialization seems to be quite a bit different than mine, maybe that's the problem?

    Here's a snippet from my PGD2007 entry's main program initialization:
    [pascal]
    // Initialize SDL
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) then
    begin
    WriteToErrorLog( Format( 'Could not initialize SDL : %s', [SDL_GetError] ), 'Application', 'Main' );
    TerminateApplication;
    end;

    // Fetch the video info
    videoInfo := SDL_GetVideoInfo;

    if ( videoInfo = nil ) then
    begin
    WriteToErrorLog( Format( 'Video query failed : %s', [SDL_GetError] ), 'Application', 'Main' );
    TerminateApplication;
    end;

    // the flags to pass to SDL_SetVideoMode
    videoFlags := SDL_OPENGL; // Enable OpenGL in SDL
    videoFlags := videoFlags or SDL_DOUBLEBUF; // Enable double buffering
    videoFlags := videoFlags or SDL_HWPALETTE; // Store the palette in hardware

    // This checks to see if surfaces can be stored in memory
    if ( videoInfo^.hw_available <> 0 ) then
    videoFlags := videoFlags or SDL_HWSURFACE
    else
    videoFlags := videoFlags or SDL_SWSURFACE;

    // This checks if hardware blits can be done * /
    if ( videoInfo^.blit_hw <> 0 ) then
    videoFlags := videoFlags or SDL_HWACCEL;

    // Set the OpenGL Attributes
    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );

    // Set the title bar in environments that support it
    SDL_WM_SetCaption( APP_NAME + ' [' + VERSION + ']', nil );


    videoflags := videoFlags or SDL_RESIZABLE; // Enable window resizing
    //videoflags := videoFlags or SDL_FULLSCREEN; // Enable window resizing
    if ReadSettings(ExtractFilePath(ParamStr(0)) + 'engine.ini') then
    begin
    if DisplayFullscreen then
    videoflags := videoFlags or SDL_FULLSCREEN;
    surface := SDL_SetVideoMode( DisplayWidth, DisplayHeight, SCREEN_BPP, videoflags );
    end
    else
    begin
    DisplayWidth := SCREEN_WIDTH;
    DisplayHeight := SCREEN_HEIGHT;
    surface := SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoflags );
    end;
    if ( surface = nil ) then
    begin
    WriteToErrorLog( Format( 'Unable to create OpenGL screen : %s', [SDL_GetError] ), 'Application', 'Main' );
    TerminateApplication;
    end;

    // Initialize game engine
    InitEngine;
    [/pascal]

    Through InitEngine:
    [pascal]
    glClearColor(0.0, 0.0, 0.0, 0.0);
    //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glCullFace(GL_BACK);
    glFrontFace(GL_CCW);
    glShadeModel(GL_SMOOTH);
    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_TEXTURE_2D);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    if not glext_LoadExtension('GL_version_1_2') then
    s := 'OpenGL version 1.2 not supported!' + #13#10;

    // Load extensions

    for i := 0 to MAX_EXTENSION do
    if glext_ExtensionSupported(PChar(Extensions[i]), #0) then
    glext_LoadExtension(Extensions[i])
    else
    s := Extensions[i] + #13#10;
    if s <> '' then
    raise EOpenGLError('All needed OpenGL extensions are not supported! Unsupported extensions: ' + #13#10 + s);
    [/pascal]

    You could try adding those extra flags and set the attributes in SDL initialization, maybe that'll help?

    I haven't used SDL that much, so I can't really help if that doesn't work...
    If you develop an idiot proof system, the nature develops better idiots.

  10. #10
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25

    How to get the seams out of tiled zooming?

    Oh man! :doh: Thats why...

    Ok, I was expecting that I had to load the extension BEFORE I initialized video. Now that I think about it, thats kinda daft. How else would SDL know about the GL loaded extensions. :lol:

    Ok well it's working and MAN! does it look pretty now.


    Thanks a ton for the help. Do you have maybe a better explanation as to why exactly the black border around the textures is removed? And whats the deal with GL_CLAMP anyhow if it doesn't apparently do much...?
    Jason McMillen
    Pascal Game Development
    Co-Founder





Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

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