OpenGL Q again

Hi,
please can someone look on this and let me know what exactly is wrong?
(i need to blit it correctly using alpha channel) Thanks for your help

// i just try tu update some nehe tutorial…

#ifdef WIN32
//#define WIN32_LEAN_AND_MEAN //if i leave this defined here then
something goes wrong
//and i don’t have functions like exit and so…but in full tutorial is it
OK.
//do u know WHY?
#include <windows.h>
#endif

#if defined(APPLE) && defined(MACH)
#include <OpenGL/gl.h> // Header File For The OpenGL32 Library
#include <OpenGL/glu.h> // Header File For The GLu32 Library
#else
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
#endif
#include “SDL.h”
#include "SDL_image.h"
float xpos,ypos;

GLuint texture[10];
GLuint raketka;

SDL_Surface *LoadIMG(char *filename)
{
SDL_Surface *image;
image = IMG_Load(filename);
if ( image == NULL ) {
fprintf(stderr, “Unable to load %s: %s\n”, filename,
SDL_GetError());
return(NULL);
}

// i don't care about colors order now.

return(image);

}

// Load Bitmaps And Convert To Textures
void LoadGLTextures(void)
{
// Load Texture
SDL_Surface *image[10];
char buffer[30];
for (int i=0; i<10; i++)
{
sprintf(buffer,“data/field%d.jpg”,i);
image[i] = LoadIMG(buffer);
glGenTextures(1, &texture[i]);
glBindTexture(GL_TEXTURE_2D, texture[i]); // 2d texture
(x and y size)

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale
linearly when image bigger than texture

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale
linearly when image smalled than texture

    glTexImage2D(GL_TEXTURE_2D, 0, 3, image[i]->w, image[i]->h, 0,

GL_RGB, GL_UNSIGNED_BYTE, image[i]->pixels);
}
SDL_Surface *rocket;
rocket = LoadIMG(“fighter1.tga”); //yes i am sure that this image
is OK. And is RGBA
glGenTextures(1, &raketka);
glBindTexture(GL_TEXTURE_2D, raketka);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //

scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //
scale linearly when image smalled than texture

glTexImage2D(GL_TEXTURE_2D, 0, 4, rocket->w, rocket->h, 0, GL_RGBA,

GL_UNSIGNED_BYTE, rocket->pixels);

};

/* A general OpenGL initialization function. Sets all of the initial
parameters. */
void InitGL(int width, int height)
{
LoadGLTextures();
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

glViewport(0,0,width,height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();


gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

}

/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // Reset The View

// glTranslatef(xpos,ypos,-4.62f);
glTranslatef(0,0,-5.0f);
float xt,yt,zt;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 2; j++)
{
glBindTexture(GL_TEXTURE_2D, texture[2i + j]);
glBegin(GL_QUADS);
xt = -2.0f + j
2;
yt = -1.0f + i*2;
glTexCoord2f(0.0f, 1.0f); glVertex3f(xt, yt, 1.0f);
xt = xt + 2.0f;
glTexCoord2f(1.0f, 1.0f); glVertex3f(xt, yt,
1.0f);
yt += 2.0f;
glTexCoord2f(1.0f, 0.0f); glVertex3f(xt, yt,
1.0f);
xt = xt - 2.0f;
glTexCoord2f(0.0f, 0.0f); glVertex3f(xt, yt,
1.0f);
glEnd();
}
}

glDisable(GL_DEPTH_TEST);

// Enables Depth Testing
glEnable(GL_BLEND);

//************************************************************************************
glBlendFunc(GL_ONE,GL_ONE);
//WHAT SHOULD BE HERE???
// i want to blit it using alpha channel (so 100% A means only
source 0% A means only
// dest)

//************************************************************************************

glBindTexture(GL_TEXTURE_2D,raketka);
glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(0,0.3f, 2.0f);
	glTexCoord2f(1.0f, 1.0f); glVertex3f(0.4f,0.3f,  2.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex3f(0.4f,0,  2.0f);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(0,0,  2.0f);
glEnd();
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
SDL_GL_SwapBuffers();

}
#define TICK_INTERVAL 30

Uint32 TimeLeft(void)
{
static Uint32 next_time = 0;
Uint32 now;
now = SDL_GetTicks();

if ( next_time <= now ) {
    next_time = now+TICK_INTERVAL;
    return(0);
}
return(next_time-now);

}
int main(int argc, char **argv)
{
int done;

if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, “Unable to initialize SDL: %s\n”, SDL_GetError());
return 1;
}

SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

if ( SDL_SetVideoMode(800, 600, 0, SDL_OPENGL) == NULL ) {
fprintf(stderr, “Unable to create OpenGL screen: %s\n”,
SDL_GetError());
SDL_Quit();
exit(2);
}

SDL_WM_SetCaption(“Test”, NULL);

InitGL(800, 600);
done = 0;
xpos = 0.0f;
ypos = 0.0f;

SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
Uint32 now,before;
now = 0; before = 0;
while ( ! done ) {
DrawGLScene();

SDL_Event event;
 while ( SDL_PollEvent(&event) ) {
    if ( event.type == SDL_QUIT ) {
      done = 1;
    }
  }

SDL_Delay(TimeLeft());
ypos -= 0.01f;

}
SDL_Quit();
return 1;
}

  image[i] = LoadIMG(buffer);

[…]

  glTexImage2D(GL_TEXTURE_2D, 0, 3, image[i]->w, image[i]->h, 0,

GL_RGB, GL_UNSIGNED_BYTE, image[i]->pixels);
[…]
rocket = LoadIMG(“fighter1.tga”); //yes i am sure that this image
is OK. And is RGBA
[…]
glTexImage2D(GL_TEXTURE_2D, 0, 4, rocket->w, rocket->h, 0, GL_RGBA,
GL_UNSIGNED_BYTE, rocket->pixels);

there is no guarantee at all that IMG_Load() or LoadBMP() return images
of a particular pixel format. The above code makes a lot of dangerous
(and probably incorrect) assumptions

You must check if the format is right, and if not, create a new surface
of your desired format and copy your image over. This has been discussed
many times on the list - see the archives. There is also some example
code in the documentation of SDL_CreateRGBSurface which you might want
to read

there is no guarantee at all that IMG_Load() or LoadBMP() return images
of a particular pixel format. The above code makes a lot of dangerous

Here is some code which have used myself. Partly adapted from SDL docs…:
Not perfect, but might give you a hint what needs to be done.
IMHO, it is weird that SDL_GetPixel() is not part of SDL…

Uint32 SDL_GetPixel( SDL_Surface *surface, Uint16 x, Uint16 y ){
SDL_PixelFormat *fmt;
SDL_Color *color;
Uint8 index;
Uint8 red;
Uint8 green;
Uint8 blue;
Uint8 alpha;
Uint32 temp;
Uint32 pixel = 255;
Uint8 *img;

fmt = surface->format;
img = (Uint8 *)surface->pixels + x*fmt->BytesPerPixel+surface->pitch*y;

/* Check the bitdepth of the surface */
if( fmt->BitsPerPixel==8 ){
	/* Get the topleft pixel */
	index = *img;
	color = &(fmt->palette->colors[index]);
	alpha = 255;
	red   = color->r;
	green = color->g;
	blue  = color->b;

}else{
	/* Extracting color components from a 32-bit color value */

	pixel = *(Uint32*)img;

	/* Get Red component */
	temp  = pixel&fmt->Rmask; /* Isolate red component */
	temp  = temp>>fmt->Rshift;/* Shift it down to 8-bit */
	temp  = temp<<fmt->Rloss; /* Expand to a full 8-bit number */
	red   = (Uint8)temp;

	/* Get Green component */
	temp  = pixel&fmt->Gmask; /* Isolate green component */
	temp  = temp>>fmt->Gshift;/* Shift it down to 8-bit */
	temp  = temp<<fmt->Gloss; /* Expand to a full 8-bit number */
	green = (Uint8)temp;

	/* Get Blue component */
	temp  = pixel&fmt->Bmask; /* Isolate blue component */
	temp  = temp>>fmt->Bshift;/* Shift it down to 8-bit */
	temp  = temp<<fmt->Bloss; /* Expand to a full 8-bit number */
	blue  = (Uint8)temp;

	/* Get Alpha component */
	temp  = pixel&fmt->Amask; /* Isolate alpha component */
	temp  = temp>>fmt->Ashift;/* Shift it down to 8-bit */
	temp  = temp<<fmt->Aloss; /* Expand to a full 8-bit number */
	alpha = (Uint8)temp;

}
return (alpha<<24) | (blue<<16) | (green<<8) | red;

}

//! Copy SDL_Surface to texture
void SdlTexture::copySdlSurface( SDL_Surface *surface ){
this->width = surface->w;
this->height = surface->h;
Uint32 data = new Uint32[widthheight];

//  Read pixels to array
SDL_LockSurface( surface );
for( int y=0; y<height; y++ ){
	for( int x=0; x<width; x++ ){
		data[x+y*width] = SDL_GetPixel( surface, x, y );
	}
}
SDL_UnlockSurface( surface );

//  OpenGL is required to handle 64 x 64 only.
//  So you don't know at compile time what sizes
//  are supported; we might need to scale or
//  split the texture. Here only scale is supported.
//  Also OpenGL only support sizes that are powers
//  of 2.
bool scale      = false;
int  new_width  = width;
int  new_height = height;
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

/*
	Scaling process should make sure that all
	texture sizes are ok to the OpenGL driver,
	which may be different on any machine.
*/
if( new_width!=minPow(new_width) ){
	new_width = minPow( new_width );
	scale     = true;
}
if( new_height!=minPow(new_height) ){
	new_height = minPow( new_height );
	scale      = true;
}

//  I simply had to hardcode upper limits
//  because I couldn't get any other way working
//  correctly on my Matrox G400 :/
if( new_width > 1024 ){
	new_width = 1024;
	scale = true;
}
if( new_height > 512 ){
	new_height = 512;
	scale = true;
}

//  See if texture size is ok for OpenGL driver
//  Does not seem to work :/
GLint format = 0;
int   x      = 0;
for(;;){
	glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, new_width, new_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
	glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format );
	if( format == 0 ){  //  if not, go down in size
		x     = 1 - x;
		scale = true;
		if( x==0 ){
			new_height = new_height / 2;  //  halve height
		}else{
			new_width  = new_width / 2;   //  halve width
		}
	}else{
		if( format == GL_RGBA8 ){
			break;  //  ok size!
		}else{
			printf( "0x%x\n", format );
			break;

/* x = 1 - x;
scale = true;
if( x==0 ){
new_height = new_height / 2;
}else{
new_width = new_width / 2;
}*/
}
}
}

//  Now do the actual scaling if needed
if( scale ){
	cout << "Doing scale from " << width << " x " << height;
	cout << " to " << new_width << " x " << new_height << endl;
	Uint32 *new_data = new Uint32[ new_width * new_height];
	gluScaleImage(
		GL_RGBA,
		width,     height,     GL_UNSIGNED_BYTE, data,
		new_width, new_height, GL_UNSIGNED_BYTE, new_data
	);
	delete[] data;
	data         = new_data;
	this->width  = new_width;
	this->height = new_height;
}
cout << "Texture size " << width << " x " << height << endl;

glBindTexture  ( GL_TEXTURE_2D,  gltid );
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_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D,  GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexEnvi      ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,   GL_MODULATE );
glTexImage2D   ( GL_TEXTURE_2D,  0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
View::check();

}

– Timo Suoranta – @Timo_K_Suoranta

IMHO, it is weird that SDL_GetPixel() is not part of SDL…

For 3 reasons:

  1. it can be implemented in a platform-independent way and thus does not need
    to be in SDL
  2. it is an inefficient way of operating on surfaces and is therefore
    rarely used
  3. it is trivial to implement for anyone with some programming experience,
    and beginners need the exercise :slight_smile:

There is a sample getpixel()/putpixel() in the SDL documentation
examples (http://sdldoc.csn.ul.ie/guidevideo.php).
Also remember SDL_GetRGB(), SDL_GetRGBA(), SDL_MapRGB(), SDL_MapRGBA().

I’ll throw together some sample code of how to load textures correctly
(your code only works on little-endian machines)

I’ve slapped together some sample code for converting surfaces to
OpenGL-ish texture format at

ftp://ptah.lnf.kth.se/pub/misc/convgltex.c

Beware: it’s completely untested, but it should at least give you a hint
of how it’s supposed to work

If someone wants to elaborate on that code we can include as an example
in the SDL docs. I’m going on vacation soon and will read my mail very
sporadically, so have fun with it

Mattias Engdeg?rd wrote:

I’ve slapped together some sample code for converting surfaces to
OpenGL-ish texture format at

ftp://ptah.lnf.kth.se/pub/misc/convgltex.c

Beware: it’s completely untested, but it should at least give you a hint
of how it’s supposed to work

If someone wants to elaborate on that code we can include as an example
in the SDL docs. I’m going on vacation soon and will read my mail very
sporadically, so have fun with it

[ From the code ]

/* SDL will pad each scanline to a multiple 4 bytes, but OpenGL does not
use padding; this only affects very small/narrow textures but can
arrive when reading mipmaps /
if(conv && bpp == 24 && (conv->w & 3)) {
/
remove padding: this will make the texture useless with
SDL, but we will only pass the data to OpenGL. */
int y;
Uint8 *dest = conv->pixels, *src = dest;
int bpl = conv->w * 3;
for(y = 0; y < conv->h; y++) {
memmove(dest, src, bpl);
src += conv->pitch;
dest += bpl;
}
}

I don’t think this is a very good idea. If SDL always pads to 4 pixels you

should just be doing this in the GL texture creation code:

 glPixelFormati(GL_UNPACK_ALIGNMENT, 4);

I’m not sure if you also need

 glPixelFormati(GL_ROW_LENGTH,
                conv->pitch/conv->format->BytesPerPixel);

I think it should be okay without it, but I haven’t thought about it as
hard as I probably should.

That way the surface is still correct for SDL use. Also if this is
going to be in the examples I don’t think it should be called
"make_gl_texture" as it doesn’t actually make any textures, just does
surface loading into the right format so you can make a texture.

  • Mike
glPixelFormati(GL_UNPACK_ALIGNMENT, 4);

ah yes, thank you (though I believe it’s glPixelStorei, not glPixelFormati)
I’m not at all familiar with openGL so what I wrote was just a guess from the
man pages. I’ll change the code (in fact UNPACK_ALIGNMENT=4 seems to be
the initial value)

Mattias Engdeg?rd wrote:

glPixelFormati(GL_UNPACK_ALIGNMENT, 4);
ah yes, thank you (though I believe it’s glPixelStorei, not glPixelFormati)

Yes, you’re right. Must have had too much windows on the brain that day.

Cheers,

  • Mike