Visual Tearing

Apprentice
Posts: 5
Joined: 2007.11
Post: #1
Hey all, I'm new to OpenGL and SDL programming but I'm trying to start learning them by starting on a small game. (Also, English is not my native language so sorry for any weird ways of saying things Rasp)

But when I move around my textured quad it gets rather choppy.. I think it's called visual tearing.. But I thought things like that wouldn't happen with a double buffer. Maybe I've not set that up right or I'm doing something else wrong. Rasp

Here's the code:
Code:
#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/openglut.h>
#include <GL/glext.h>

class Sprite
{
  public:
    int x, y;
    int w, h;
    float r;
    GLuint texture;
};

void Display(Sprite);
void InitScreen();
Sprite LoadSprite(char*, int, int, float);

Sprite smiley;
Sprite smiley2;

int main(int argc, char* argv[])
{
  SDL_Init(SDL_INIT_VIDEO);
  SDL_WM_SetCaption("OpenGL test", NULL);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  SDL_SetVideoMode(640, 480, 32, SDL_OPENGL);
  
  bool keepdoing = true;
  SDL_Event event;
  
  InitScreen();
  
  smiley = LoadSprite("smiley.bmp", 80, 80, 0);
  smiley2 = LoadSprite("smiley2.bmp", 300, 300, 0);
  Uint8* KeyStates;
  
  while(keepdoing)
  {
    while(SDL_PollEvent(&event))
    {
      if(event.type == SDL_QUIT){ keepdoing = false; }
    }
    
    KeyStates = SDL_GetKeyState(NULL);
    
    if(KeyStates[SDLK_UP]){ smiley.y -= 4; }
    if(KeyStates[SDLK_DOWN]){ smiley.y += 4; }
    if(KeyStates[SDLK_LEFT]){ smiley.x -= 4; }
    if(KeyStates[SDLK_RIGHT]){ smiley.x += 4; }
    if(KeyStates[SDLK_r]){ smiley.r += 2; }
    
    glClear(GL_COLOR_BUFFER_BIT);
    
    Display(smiley);
    Display(smiley2);
    
    glFlush();
    SDL_GL_SwapBuffers();
  }
  
  SDL_Quit();
  
  return 0;
}

void Display(Sprite sprite)
{
  float tX = sprite.w/2;
  float tY = sprite.h/2;
  
  glPushMatrix();
  
  glTranslatef(sprite.x, sprite.y, 0);
  glRotatef(sprite.r, 0, 0, 1);
  
  glBindTexture(GL_TEXTURE_2D, sprite.texture);
  
  glBegin(GL_QUADS);
    glTexCoord2i(0,0); glVertex2d(-tX, -tY);
    glTexCoord2i(1,0); glVertex2d(tX, -tY);
    glTexCoord2i(1,1); glVertex2d(tX, tY);
    glTexCoord2i(0,1); glVertex2d(-tX, tY);
  glEnd();
  
  glPopMatrix();
}

void InitScreen()
{
  glClearColor(0,0,0,0);
  glViewport(0, 0, 640, 480);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, 640, 480, 0, -100, 100);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glEnable(GL_TEXTURE_2D);
  glDisable(GL_CULL_FACE);
}

Sprite LoadSprite(char* file, int x, int y, float r)
{
  Sprite sprite;
  SDL_Surface* surface = SDL_LoadBMP(file);
  GLuint tex;
  
  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  glGenTextures(1, &tex);
  glBindTexture(GL_TEXTURE_2D, tex);
  glTexImage2D(GL_TEXTURE_2D, 0, 3, surface->w, surface->h , 0, GL_BGR,
               GL_UNSIGNED_BYTE, surface->pixels);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  
  sprite.w = surface->w;
  sprite.h = surface->h;
  sprite.texture = tex;
  sprite.x = x;
  sprite.y = y;
  sprite.r = r;
  
  SDL_FreeSurface(surface);
  
  return sprite;
}

Thanks in advance ^^.
Quote this message in a reply
Moderator
Posts: 452
Joined: 2008.04
Post: #2
Try turning on vbl sync.
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #3
Code:
#include <OpenGL/OpenGL.h>        // For VBL
...
long swapInterval = 1;
CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &swapInterval);
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #4
Or if you want to do it the SDL way:
Code:
SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1);

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Apprentice
Posts: 5
Joined: 2007.11
Post: #5
Thanks for the replies, I added SDL_GL_SetAttribute (SDL_GL_SWAP_CONTROL, 1) here:

Code:
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
SDL_SetVideoMode(640, 480, 32, SDL_OPENGL);

But this tearing still happens Annoyed Maybe it's my graphics card? It's an nVidia GeForce 7300 GT.

Also I'm compiling this in Windows. I'm not sure if it matters since I'm using OpenGL + SDL but i thought I'd mention it in case it does make a differenceWink
Quote this message in a reply
Apprentice
Posts: 11
Joined: 2007.02
Post: #6
I don't know for sure, but I've never issued the function glFlush() in my programs. But on the other hand, I might not see that actual tearing. You could try leaving it out anyway. Smile
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #7
You definitely don't need or want the glFlush(). At best it's a performance penalty, at worst, it could cause something like tearing.
Quote this message in a reply
Apprentice
Posts: 5
Joined: 2007.11
Post: #8
Hmmm I removed the glFlush() but it still shows tearing :S

This is updated code:
Code:
#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/openglut.h>
#include <GL/glext.h>

class Sprite
{
  public:
    int x, y;
    int w, h;
    float r;
    GLuint texture;
};

void Display(Sprite);
void InitScreen();
Sprite LoadSprite(char*, int, int, float);

Sprite smiley;

int main(int argc, char* argv[])
{
  SDL_Init(SDL_INIT_VIDEO);
  SDL_WM_SetCaption("OpenGL test", NULL);
  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
  SDL_SetVideoMode(640, 480, 0, SDL_OPENGL | SDL_FULLSCREEN);
  
  bool keepdoing = true;
  SDL_Event event;
  
  InitScreen();
  
  smiley = LoadSprite("smiley.bmp", 80, 80, 0);
  Uint8* KeyStates;
  
  while(keepdoing)
  {
    while(SDL_PollEvent(&event))
    {
      if(event.type == SDL_QUIT){ keepdoing = false; }
    }
    
    KeyStates = SDL_GetKeyState(NULL);
    
    if(KeyStates[SDLK_UP]){ smiley.y -= 4; }
    if(KeyStates[SDLK_DOWN]){ smiley.y += 4; }
    if(KeyStates[SDLK_LEFT]){ smiley.x -= 4; }
    if(KeyStates[SDLK_RIGHT]){ smiley.x += 4; }
    if(KeyStates[SDLK_r]){ smiley.r += 2; }
    
    glClear(GL_COLOR_BUFFER_BIT);
    
    Display(smiley);
    
    SDL_GL_SwapBuffers();
  }
  
  SDL_Quit();
  
  return 0;
}

void Display(Sprite sprite)
{
  float tX = sprite.w/2;
  float tY = sprite.h/2;
  
  glPushMatrix();
  
  glTranslatef(sprite.x, sprite.y, 0);
  glRotatef(sprite.r, 0, 0, 1);
  
  glBindTexture(GL_TEXTURE_2D, sprite.texture);
  
  glBegin(GL_QUADS);
    glTexCoord2i(0,0); glVertex2d(-tX, -tY);
    glTexCoord2i(1,0); glVertex2d(tX, -tY);
    glTexCoord2i(1,1); glVertex2d(tX, tY);
    glTexCoord2i(0,1); glVertex2d(-tX, tY);
  glEnd();
  
  glPopMatrix();
}

void InitScreen()
{
  glClearColor(0,0,0,0);
  glViewport(0, 0, 640, 480);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, 640, 480, 0, -100, 100);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glEnable(GL_TEXTURE_2D);
  glDisable(GL_CULL_FACE);
}

Sprite LoadSprite(char* file, int x, int y, float r)
{
  Sprite sprite;
  SDL_Surface* surface = SDL_LoadBMP(file);
  GLuint tex;
  
  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  glGenTextures(1, &tex);
  glBindTexture(GL_TEXTURE_2D, tex);
  glTexImage2D(GL_TEXTURE_2D, 0, 3, surface->w, surface->h , 0, GL_BGR,
               GL_UNSIGNED_BYTE, surface->pixels);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  
  sprite.w = surface->w;
  sprite.h = surface->h;
  sprite.texture = tex;
  sprite.x = x;
  sprite.y = y;
  sprite.r = r;
  
  SDL_FreeSurface(surface);
  
  return sprite;
}
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #9
Try putting the SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1) call after the call to SDL_SetVideoMode.

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #10
Arjan B Wrote:Also I'm compiling this in Windows.

1) observe the "Macintosh" text at the top left of this forum.
2) go to your Windows driver control panel and look for a setting that forces VBL on, or puts under "application control".
Quote this message in a reply
Apprentice
Posts: 5
Joined: 2007.11
Post: #11
reubert Wrote:Try putting the SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1) call after the call to SDL_SetVideoMode.

Had already tried that ^^.

arekkusu Wrote:1) observe the "Macintosh" text at the top left of this forum.
2) go to your Windows driver control panel and look for a setting that forces VBL on, or puts under "application control".

I know this is a forum for game development for mac but since I was using SDL and OpenGL i thought it wouldn't matter and this seemed like a very good forum to get help with a problem like this.. And it is because a lot of people are trying to help me ^^.

I didn't see any VBL in the control panel but in my nVidia control panel the vertical synchronisation is set to "Let 3D-Application decide".



Does anyone know of a book using SDL and OpenGL for 2D game programming? I've searched around pretty much but couldn't find any.. Books on SDL, Books on OpenGL, books on 2D game programming but no combination of the 3.
If anyone knows of one I'll just read through that and I'll probably figure out myself what is wrong with the above code and reply a solution here later^^.
Quote this message in a reply
Apprentice
Posts: 5
Joined: 2007.11
Post: #12
I've tried it on two others computers and works fine there.. I guess the problem is my computer..

Thanks for your help all.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Weird Windowed Mode GFX Tearing nabobnick 2 2,850 Jul 25, 2005 06:45 PM
Last Post: nabobnick
  need help with a tearing like graphics glitch Andrew 19 7,931 Jun 9, 2005 09:41 AM
Last Post: Andrew
  Need ideas for superfluous visual effects stevejohnson 2 3,144 Apr 27, 2005 06:46 PM
Last Post: stevejohnson
  nasty tearing when I scroll in openGL Joseph Duchesne 3 3,207 Aug 15, 2004 10:30 PM
Last Post: arekkusu