Page 6 of 8

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 8:35 am
by mv2112
Im starting to sort of get the hang of the basics of openGL, however im trying to load a texture from an SDL_surface and its loading wrong. When i render the texture it is inverted and it has no red...
http://pastebin.com/psMhrpwb
My load texture func^^

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 10:34 am
by XianForce
I'm sorry for not going through your code before I post, but the two solutions that instantly pop into my head are:

1) Your not matching your vertex coordinates and texture coordinates up right... That can cause the image to be flipped
2) When your rendering the opaque quad, you don't have any red in it.


So like if I had an image of a white circle and tried to render it onto a green quad (0, 1.0, 0 - rgb format), the circle will actually be green when rendered.

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 2:57 pm
by dandymcgee

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 4:29 pm
by mv2112
I got the code i'm using partly from the 4'th post on that thread

I also didnt mean to say inverted, i meant that the image is slightly rotated and mirrored so its the same image twice and the color red is gone...
Link to image

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 4:35 pm
by mv2112
I got the colors right, but the image is still mirrored, like the link i posted but with normal colors...

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 4:45 pm
by dandymcgee
mv2112 wrote:I got the colors right, but the image is still mirrored, like the link i posted but with normal colors...
That's a texCoord mistake like XianForce mentioned earlier. Read up on ordering vertices and texture coordinates properly in opengl. (Hint: Get it right first without TexCoords using only colored vertices, then add the texture into the mix.)

Edit: Maybe this will help: http://www.gamedev.net/reference/articl ... cle947.asp (Scroll down to the bottom "A Textured Quad").

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 5:30 pm
by mv2112
dandymcgee wrote:
mv2112 wrote:I got the colors right, but the image is still mirrored, like the link i posted but with normal colors...
That's a texCoord mistake like XianForce mentioned earlier. Read up on ordering vertices and texture coordinates properly in opengl. (Hint: Get it right first without TexCoords using only colored vertices, then add the texture into the mix.)

Edit: Maybe this will help: http://www.gamedev.net/reference/articl ... cle947.asp (Scroll down to the bottom "A Textured Quad").
Yup, thats what it was. However now if i render another primitive that is colored, that color bleeds on to the texture. I rendered a red square and my texture turned red. How can i fix this...

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 6:17 pm
by XianForce
mv2112 wrote:
dandymcgee wrote:
mv2112 wrote:I got the colors right, but the image is still mirrored, like the link i posted but with normal colors...
That's a texCoord mistake like XianForce mentioned earlier. Read up on ordering vertices and texture coordinates properly in opengl. (Hint: Get it right first without TexCoords using only colored vertices, then add the texture into the mix.)

Edit: Maybe this will help: http://www.gamedev.net/reference/articl ... cle947.asp (Scroll down to the bottom "A Textured Quad").
Yup, thats what it was. However now if i render another primitive that is colored, that color bleeds on to the texture. I rendered a red square and my texture turned red. How can i fix this...
Render a white primitive.

From what I understand, the texture that is mapped to a primitive, can only use what color(s) is/are available from the primitive.

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 6:30 pm
by qpHalcy0n
The default pixel modulation operation is GL_MODULATE.

This takes the source color and source texel data and performs a mix of them by color multiplication. If you want the texture to appear as it does on its own, simply don't pass a color when rendering, or change the modulation op to GL_REPLACE.

glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

Rendering a white primitive will fix the problem in a roundabout way ( any texel source color multiplied by one is itself ). That is what's going on there for you.

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 7:17 pm
by XianForce
qpHalcy0n wrote:The default pixel modulation operation is GL_MODULATE.

This takes the source color and source texel data and performs a mix of them by color multiplication. If you want the texture to appear as it does on its own, simply don't pass a color when rendering, or change the modulation op to GL_REPLACE.

glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

Rendering a white primitive will fix the problem in a roundabout way ( any texel source color multiplied by one is itself ). That is what's going on there for you.
Oooh, thanks for explaining that =D. Learning something new everyday haha.

Re: mvEngine Development Thread

Posted: Mon Aug 02, 2010 8:08 pm
by mv2112
I'm starting to like openGL. I just learned how to rotate an object around it's center! My adventure through openGL continues...

Re: mvEngine Development Thread

Posted: Thu Aug 05, 2010 12:52 pm
by eatcomics
I love OGL too :D its like the god of graphics APIs

Re: mvEngine Development Thread

Posted: Fri Aug 06, 2010 12:12 am
by mv2112
So i've been using SDL_Surfaces to load images and i though i would try to load a bitmap manually and i almost succeeded, However the image appears black and white. I was basing my code off of this dudes code. After learing about bit operations and stuff like that, i understand most of the code i wrote but not exactly how the pixel data is organized in the arrays, here is the code i wrote:

Code: Select all

GLuint LoadBMP(const char*file)
{
	ifstream File;
	char shortbuffer[2], intbuffer[4];
	unsigned int Offset=NULL;
	unsigned int header=NULL;
	signed int width=NULL;
	signed int height=NULL;
	int bpr=NULL;
	int size=NULL;
	
	File.open(file,ifstream::binary);
	File.read(shortbuffer,2); //format check
	if(shortbuffer[0]!='B'||shortbuffer[1]!='M')
	{
		File.close();
		assert(!"Error 1");
		return NULL;
	}
	File.ignore(8); //skip the next 4,2 and 2 bytes
	//get buffer offset for pixel data
	File.read(intbuffer,4);
	Offset=(((unsigned char)intbuffer[3]<<24)|
			((unsigned char)intbuffer[2]<<16)|
			((unsigned char)intbuffer[1]<<8)|
			((unsigned char)intbuffer[0]));
	intbuffer={0,0,0,0};
	File.read(intbuffer,4);
	header=(((unsigned char)intbuffer[3]<<24)|
			((unsigned char)intbuffer[2]<<16)|
			((unsigned char)intbuffer[1]<<8)|
			((unsigned char)intbuffer[0]));
	intbuffer={0,0,0,0};
	if(header!=40)
	{
		File.close();
		assert(!"Error 2");
		return NULL;
	}
	File.read(intbuffer,4);
	width=(((unsigned char)intbuffer[3]<<24)|
			((unsigned char)intbuffer[2]<<16)|
			((unsigned char)intbuffer[1]<<8)|
			((unsigned char)intbuffer[0]));
	File.read(intbuffer,4);
	height=(((unsigned char)intbuffer[3]<<24)| //shift in reverse order becuase they were written from left to right maybe?
			((unsigned char)intbuffer[2]<<16)|
			((unsigned char)intbuffer[1]<<8)|
			((unsigned char)intbuffer[0]));
	
	bpr=((width * 3 + 3) / 4) * 4 - (width * 3 % 4); //dont get this
	size=bpr*height;
	
	char*buffer=new char[size];
	char*data=new char[width*height*3];
	
	File.seekg(Offset,std::ios_base::beg);
	File.read(buffer,size);
	
	for(int y=0;y<height;y++)
	{
		for(int x=0;x<width;x++)
		{
			for(int c=0;c<3;c++)
			{
				data[3 * (width * y + x) + c]=buffer[bpr * y + 3 * x + (2 - c)]; //dont get this either...
			}
		}
	}
	File.close();
	delete [] buffer;
	GLuint Texture;
	glGenTextures(1,&Texture);
	glBindTexture(GL_TEXTURE_2D,Texture);
	
	glTexImage2D(GL_TEXTURE_2D,0,3,width,height,0,GL_BGR,GL_UNSIGNED_BYTE,data);
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glFinish();
    delete [] data;
	return Texture;
}
I mostly dont understand the code inside the triple for loop. Can anyone fill me in? Thanks.

Re: mvEngine Development Thread

Posted: Fri Aug 06, 2010 2:01 am
by qpHalcy0n
Alright, I'm going to save you some time and just tell you that this guy's code is barre none some of the WORST image loading code I have ever seen in my entire life. It is needlessly arcane, it is totally incomplete (he leaves out things in the header that would make this significantly easier), and not to mention, this won't work on all bitmaps.

The size of a structure or class is the size of the types that make it up. IN ORDER! This is key. So rather than doing this horrendously arcane bitshift junk for header reading (although, sure it's "cool" and you can "wow" people with it...although those who know what they're doing will scoff at it), you can simply read in the headers (bitmap has 2 of them) as a single object.

The header layout is like so:

Code: Select all

typedef struct
{
    unsigned short type;                     // Will code out to 0x4D42 which is 19778 in decimal. This equates to "BM" in 8 bit ASCII
    unsigned int     size;                     // This is the size of the chunk
    unsigned short  reserved1;            // Reserved
    unsigned short  reserved2;            // Reserved
    unsigned int      offsetBits;            // pixmap offset (in bytes from beginning of file)
} s_bitmap_header;


typedef struct
{
    unsigned int      bmpSize;               // Pixmap size (bytes)
    int                    bmpWidth;            // Pixmap width (pixels)
    int                    bmpHeight;           // Pixmap height (pixels)
    unsigned short   bmpPlanes;           // Image bitplanes
    unsigned short   bmpBitDepth;        // Image depth (bits per pixel)     <--- important
    unsigned int       bmpCompress;      // Compression tag
    unsigned int       bmpImageSize;      // Physical size
    int                     bmpXPixelsPerMeter;     // Physical size in meters on x
    int                     bmpYPixelsPerMeter;     // Physical size in meters on y
    unsigned int       bmpClrUsed;              
    unsigned int       bmpClrImportant;          
} s_bitmap_info_header;
Now when you read it, it becomes very simple:

Code: Select all

// Assuming you have a valid FILE
FILE* bmpFile;
if( ( bmpFile = fopen( fileName, "rb" ) ) == NULL )
        return false;  //gtfo


// Read Header //
s_bitmap_header fHeader;
fread( &fHeader, sizeof( s_bitmap_header ), 1, bmpFile ); 

// Magic number doesnt check out //
if( fHeader.type != 19778 )
{
      fclose( bmpFile );
      return false;
}

// Read second header //
s_bitmap_info_header fInfoHeader;
fread( &fInfoHeader, sizeof( s_bitmap_info_header ), 1, bmpFile );

int imgWidth = fInfoHeader.bmpWidth;
int imgHeight = fInfoHeader.bmpHeight;
int bpp           = fInfoHeader.bmpBitDepth;

// Allocate the pixmap //
unsigned int pixmapSize = imgWidth * imgHeight * ( bpp / 8 );          // bpp / 8 yields size in bytes
unsigned char* pix = new unsigned char[pixmapSize];

// Read pixmap into buffer //
fread( pix, sizeof( unsigned char ), totalSize, bmpFile );

// Ba-da-bing....clean up your shit, do whatever else you have to do, and done //
}

Re: mvEngine Development Thread

Posted: Fri Aug 06, 2010 11:44 pm
by mv2112
qpHalcy0n wrote:

Code: Select all

// Assuming you have a valid FILE
FILE* bmpFile;
if( ( bmpFile = fopen( fileName, "rb" ) ) == NULL )
        return false;  //gtfo


// Read Header //
s_bitmap_header fHeader;
fread( &fHeader, sizeof( s_bitmap_header ), 1, bmpFile ); 

// Magic number doesnt check out //
if( fHeader.type != 19778 )
{
      fclose( bmpFile );
      return false;
}

// Read second header //
s_bitmap_info_header fInfoHeader;
fread( &fInfoHeader, sizeof( s_bitmap_info_header ), 1, bmpFile );

int imgWidth = fInfoHeader.bmpWidth;
int imgHeight = fInfoHeader.bmpHeight;
int bpp           = fInfoHeader.bmpBitDepth;

// Allocate the pixmap //
unsigned int pixmapSize = imgWidth * imgHeight * ( bpp / 8 );          // bpp / 8 yields size in bytes
unsigned char* pix = new unsigned char[pixmapSize];

// Read pixmap into buffer //
fread( pix, sizeof( unsigned char ), totalSize, bmpFile );

// Ba-da-bing....clean up your shit, do whatever else you have to do, and done //
}
Where do you get the totalSize variable in the last fread() function?