Drawing 2 quads with 2 different textures

So i am working on 2D and with SDL and OpenGL.

I got it to work with using 1 quad with 1 texture on it, and moving it around with keyboard. Then i thought that i could add one more quad with another texture that just stays in place, while i move around the other quad with the other texture.

My code:


/*******************************************************************
 *                                                                 *
 *                        Using SDL With OpenGL                    *
 *                                                                 *
 *                    Tutorial by Kyle Foley (sdw)                 *
 *                                                                 *
 * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
 *                                                                 *
 *******************************************************************/

#include "SDL/SDL.h"
#include <stdio.h>
#include <string.h>
#include "SDL/SDL_image.h"
#include <stdbool.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <stdio.h>

//The event structure
SDL_Event event;

float degree = 0.0f;
float x_pos=0.0f,y_pos=0.0f;
int check=0;
float size=0.0f;

GLuint texture; // Texture object handle

//Make sure the program waits for a quit
bool quit = false;


// Load the OpenGL texture
SDL_Surface *surface; // Gives us the information to make the texture

GLuint loadImage(char *path, GLuint tx,SDL_Surface* sur)
{
	if ( (sur = IMG_Load(path)) )
	{

		// Check that the image's width is a power of 2
		if ( (sur->w & (sur->w - 1)) != 0 ) {
			printf("warning: image.bmp's width is not a power of 2
");
		}

		// Also check if the height is a power of 2
		if ( (sur->h & (sur->h - 1)) != 0 ) {
			printf("warning: image.bmp's height is not a power of 2
");
		}

		// Have OpenGL generate a texture object handle for us
		glGenTextures( 1, &tx );

		// Bind the texture object
		glBindTexture( GL_TEXTURE_2D, tx );

		// Set the texture's stretching properties
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

		// Edit the texture object's image data using the information SDL_Surface gives us
		glTexImage2D( GL_TEXTURE_2D, 0, 3, sur->w, sur->h, 0,
					  GL_BGR, GL_UNSIGNED_BYTE, sur->pixels );
	}
	else
	{
		printf("SDL could not load image.bmp: %s
", SDL_GetError());
		SDL_Quit();
		return 1;
	}

	// Free the SDL_Surface only if it was successfully created
	if ( sur )
	{
		SDL_FreeSurface( sur );
	}

	return tx;
}
int drawScene( GLuint tx ,float x,float y,float s)
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	glLoadIdentity( );

    // Bind the texture to which subsequent calls refer to
    glBindTexture( GL_TEXTURE_2D, tx );

	glTranslatef(x_pos,y_pos,0.0f);
	glRotatef(degree,0.0f,0.0f,1.0f);

    glBegin( GL_QUADS );

        // Top-left vertex (corner)
        glTexCoord2i( 0, 0 );
        glVertex3f( s, s, 0 );

        // Bottom-left vertex (corner)
        glTexCoord2i( 1, 0 );
        glVertex3f( 228, s, 0 );

        // Bottom-right vertex (corner)
        glTexCoord2i( 1, 1 );
        glVertex3f( 228, 228, 0 );

        // Top-right vertex (corner)
        glTexCoord2i( 0, 1 );
        glVertex3f( s, 228, 0 );

    glEnd();

    SDL_GL_SwapBuffers();

    return (true);
}

void moveLeft()
{
	x_pos=x_pos-0.1f;
	if(x_pos<-35)
	{
		x_pos=-35;
	}
}

void moveRight()
{
	x_pos=x_pos+0.1f;
}

void moveUp()
{
	y_pos=y_pos-0.1f;
}

void moveDown()
{
	y_pos=y_pos+0.1f;
}

void rotateRight()
{
	degree=degree+0.1f;
}

void rotateLeft()
{
	degree=degree-0.1f;
}

int main(int argc, char *argv[])
{
    SDL_Surface *screen;

    // Slightly different SDL initialization
    if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
        printf("Unable to initialize SDL: %s
", SDL_GetError());
        return 1;
    }

    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*

    screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
    if ( !screen ) {
		printf("Unable to set video mode: %s
", SDL_GetError());
		return 1;
	}
	
    // Set the OpenGL state after creating the context with SDL_SetVideoMode

	glClearColor( 0, 0, 0, 0 );
	
	glEnable( GL_TEXTURE_2D ); // Need this to display a texture

    glViewport( 0, 0, 640, 480 );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    glOrtho( 0, 640, 480, 0, -1, 1 );
    
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    
    GLuint tx1,tx2;
    SDL_Surface *characters;

    tx1=loadImage("nehe1.bmp",tx1,characters);
	drawScene(tx1,x_pos,y_pos,size);

	tx2=loadImage("star.png",tx2,characters);
	drawScene(tx2,40.0f,2.0f,size-30.0f);

	while( quit == false )
	{
		//Get the keystates
		Uint8 *keystates = SDL_GetKeyState( NULL );

		//While there's an event to handle
		while( SDL_PollEvent( &event ) )
		{
			//If the user has Xed out the window
			if( event.type == SDL_QUIT )
			{
				//Quit the program
				// Free the SDL_Surface only if it was successfully created
				if ( screen ) {
					SDL_FreeSurface( screen );
				}
				quit = true;
			}
		}

		if(keystates[ SDLK_e ])
		{
			rotateRight();
			drawScene(tx1,x_pos,y_pos,size);
		}
		if(keystates[ SDLK_q ])
		{
			rotateLeft();
			drawScene(tx1,x_pos,y_pos,size);
		}
		if(keystates[ SDLK_d ])
		{
			//x_pos=x_pos+0.1f;
			moveRight();
			drawScene(tx1,x_pos,y_pos,size);
		}
		if(keystates[ SDLK_a ])
		{
			//x_pos=x_pos-0.1f;
			moveLeft();
			drawScene(tx1,x_pos,y_pos,size);
		}
		if(keystates[ SDLK_w ])
		{
			//x_pos=x_pos-0.1f;
			moveUp();
			drawScene(tx1,x_pos,y_pos,size);
		}
		if(keystates[ SDLK_s ])
		{
			//x_pos=x_pos-0.1f;
			moveDown();
			drawScene(tx1,x_pos,y_pos,size);
		}
	}
    
    // Now we can delete the OpenGL texture and close down SDL
    glDeleteTextures( 1, &texture );
    
    SDL_Quit();
    
	return 0;
}

But it first shows up the second texture only and if I touch the W,A,S,D buttons it disappears and it moves the first quad…I don’t want the second quad to disappear -.-.

You need to understand that whenever you swapbuffers, you have to clear and redraw the complete scene.

so move up the clear/loadidentity, as well as swapbuffers, something like that :


#pseudo code
drawCompleteScene(tx1,x1_pos,y1_pos,size1, tx2,x2_pos,y2_pos,size2) {

	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glLoadIdentity( );
  drawScene( tx1,x1_pos,y1_pos,size1);
  drawScene( tx2,x2_pos,y2_pos,size2);
    SDL_GL_SwapBuffers();
}

Okey thank you I see, so i have to first do the changes and then swap the screen.

Now 2 images appear on the screen, one over the other.
Something wierd is that when i press W,A,S,D both of the pictures move at the same time. It was intended that one should move and one to stay in place.

The thing i dont understand is htat for example if you have a background and a character and if you move the carachter you need to clear the screen, draw the background again and draw the characters new position again? Cant the background just remain and character be drawn in new position?

The part that i changed i marked with “**********”.


/*******************************************************************
 *                                                                 *
 *                        Using SDL With OpenGL                    *
 *                                                                 *
 *                    Tutorial by Kyle Foley (sdw)                 *
 *                                                                 *
 * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
 *                                                                 *
 *******************************************************************/

#include "SDL/SDL.h"
#include <stdio.h>
#include <string.h>
#include "SDL/SDL_image.h"
#include <stdbool.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <stdio.h>

//The event structure
SDL_Event event;

float degree = 0.0f;
float x_pos=0.0f,y_pos=0.0f;
int check=0;
float size=0.0f;

GLuint texture; // Texture object handle
GLuint character;
GLuint bg;

//Make sure the program waits for a quit
bool quit = false;

// Load the OpenGL texture
SDL_Surface *surface; // Gives us the information to make the texture

GLuint loadImage(char *path, GLuint tx,SDL_Surface* sur)
{
	if ( (sur = IMG_Load(path)) )
	{

		// Check that the image's width is a power of 2
		if ( (sur->w & (sur->w - 1)) != 0 ) {
			printf("warning: image.bmp's width is not a power of 2
");
		}

		// Also check if the height is a power of 2
		if ( (sur->h & (sur->h - 1)) != 0 ) {
			printf("warning: image.bmp's height is not a power of 2
");
		}

		// Have OpenGL generate a texture object handle for us
		glGenTextures( 1, &tx );

		// Bind the texture object
		glBindTexture( GL_TEXTURE_2D, tx );

		// Set the texture's stretching properties
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

		// Edit the texture object's image data using the information SDL_Surface gives us
		glTexImage2D( GL_TEXTURE_2D, 0, 3, sur->w, sur->h, 0,
					  GL_BGR, GL_UNSIGNED_BYTE, sur->pixels );
	}
	else
	{
		printf("SDL could not load image.bmp: %s
", SDL_GetError());
		SDL_Quit();
		return 1;
	}

	// Free the SDL_Surface only if it was successfully created
	if ( sur )
	{
		SDL_FreeSurface( sur );
	}

	return tx;
}
int drawSmiley( GLuint tx ,float x,float y,float s)
{
    // Bind the texture to which subsequent calls refer to
    glBindTexture( GL_TEXTURE_2D, tx );

	glTranslatef(x,y,0.0f);
	glRotatef(degree,0.0f,0.0f,1.0f);

    glBegin( GL_QUADS );

        // Top-left vertex (corner)
        glTexCoord2i( 0, 0 );
        glVertex3f( s, s, 0 );

        // Bottom-left vertex (corner)
        glTexCoord2i( 1, 0 );
        glVertex3f( 228, s, 0 );

        // Bottom-right vertex (corner)
        glTexCoord2i( 1, 1 );
        glVertex3f( 228, 228, 0 );

        // Top-right vertex (corner)
        glTexCoord2i( 0, 1 );
        glVertex3f( s, 228, 0 );

    glEnd();

    return (true);
}

void moveLeft()
{
	x_pos=x_pos-0.1f;
	if(x_pos<-35)
	{
		x_pos=-35;
	}
}

void moveRight()
{
	x_pos=x_pos+0.1f;
}

void moveUp()
{
	y_pos=y_pos-0.1f;
}

void moveDown()
{
	y_pos=y_pos+0.1f;
}

void rotateRight()
{
	degree=degree+0.1f;
}

void rotateLeft()
{
	degree=degree-0.1f;
}

int main(int argc, char *argv[])
{
    SDL_Surface *screen;

    // Slightly different SDL initialization
    if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
        printf("Unable to initialize SDL: %s
", SDL_GetError());
        return 1;
    }

    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*

    screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
    if ( !screen ) {
		printf("Unable to set video mode: %s
", SDL_GetError());
		return 1;
	}

	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	
    // Set the OpenGL state after creating the context with SDL_SetVideoMode

	glClearColor( 0, 0, 0, 0 );
	
	glEnable( GL_TEXTURE_2D ); // Need this to display a texture

    glViewport( 0, 0, 640, 480 );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    glOrtho( 0, 640, 480, 0, -1, 1 );
    
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    
    GLuint txu,tx1,tx2;
    SDL_Surface *characters;

    //********************
        tx1=loadImage("nehe1.bmp",txu,characters);
	tx2=loadImage("star.png",txu,characters);
	drawSmiley(tx1,x_pos,y_pos,size);
	drawSmiley(tx2,200.0f,2.0f,size-30.0f);

	SDL_GL_SwapBuffers(); //******************

	while( quit == false )
	{
		//Get the keystates
		Uint8 *keystates = SDL_GetKeyState( NULL );

		//While there's an event to handle
		while( SDL_PollEvent( &event ) )
		{
			//If the user has Xed out the window
			if( event.type == SDL_QUIT )
			{
				//Quit the program
				// Free the SDL_Surface only if it was successfully created
				if ( screen ) {
					SDL_FreeSurface( screen );
				}
				quit = true;
			}
		}
//*************************
		if(keystates[ SDLK_e ])
		{
			rotateRight();
		}
		if(keystates[ SDLK_q ])
		{
			rotateLeft();
		}
		if(keystates[ SDLK_d ])
		{
			//x_pos=x_pos+0.1f;
			moveRight();
		}
		if(keystates[ SDLK_a ])
		{
			//x_pos=x_pos-0.1f;
			moveLeft();
		}
		if(keystates[ SDLK_w ])
		{
			//x_pos=x_pos-0.1f;
			moveUp();
		}
		if(keystates[ SDLK_s ])
		{
			//x_pos=x_pos-0.1f;
			moveDown();
		}
		glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
		glLoadIdentity( );

		drawSmiley(tx1,x_pos,y_pos,size);
		drawSmiley(tx2,200.0f,2.0f,size-30.0f);

		SDL_GL_SwapBuffers();
	}
//***********************************************************
    // Now we can delete the OpenGL texture and close down SDL
    glDeleteTextures( 1, &texture );
    
    SDL_Quit();
    
	return 0;
}

glTranslatef and glRotatef modify the current modelview matrix, so each time you do it, everything is affected, incrementally.
To “undo” the changes, use glPushMatrix() at the first line of drawSmiley, and glPopMatrix() at the last.

You should try to skim through a few beginners tutorials, this is really really basic stuff - ie. annoying to explain again and again if you see what I mean :slight_smile:
http://nehe.gamedev.net/
http://www.lighthouse3d.com/opengl/tutorials.shtml