Loading png as opengl texture problem.

BlitzMax Forums/OpenGL Module/Loading png as opengl texture problem.

*(Posted 2011) [#1]
Hi what I have is this:
	Method LoadTexture(Filename:String)
		Local TXMap:TPixmap
		Local PointeurImg:Byte Ptr
		
		If TextureEnabled = False Then
			If FileType(Filename)=0 Then RuntimeError Filename+" not found!"
			Select Upper( ExtractExt( Filename ) )
			Case "PNG"
				TXMap:TPixmap = LoadPixmapPNG( Filename )
			Case "JPG", "JPEG"
				TXMap:TPixmap = LoadPixmapJPeg( Filename )
			Default		'for bmp and tga which are uncompressed
				TXMap:TPixmap = LoadPixmap( Filename )
			End Select
			If Not TXMap Then RuntimeError "Could not load texture!"
			Texture = GLTexFromPixmap( TXMap )
			If Not Texture Then RuntimeError "Could not load texture to memory!"
			TextureEnabled = True
			Width = TXMap.Width
			Height = TXMap.Height
			
			Local CheckImage:Byte[ Width, Height, 4]
			PointeurImg=PixmapPixelPtr( TXMap, 0, 0 )
			Local pp:Int=0

			'reverse the image
			For Local y:Int=Height-1 To 0 Step -1
				For Local x:Int=0 To Width-1
					Checkimage[y,x,0]=PointeurImg[pp]
					Checkimage[y,x,1]=PointeurImg[pp+1]
					Checkimage[y,x,2]=PointeurImg[pp+2]
					Checkimage[y,x,3]=100
					pp=pp+3
				Next
			Next
		
			TXMap = Null
			
			glPixelStorei( GL_UNPACK_ALIGNMENT, 1 )
			glGenTextures(1, Varptr Texture )
			glBindTexture(GL_TEXTURE_2D, Texture )
			glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );	'setup the texture parameters
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Checkimage)
		EndIf
	End Method


But when I load png's all I get is a garbled mess is there something that I should do to get it to load correctly, bmp's load perfect as I have some of those for testing too. Anyone have any ideas?

Thanks in advance


jkrankie(Posted 2011) [#2]
any use?

Function AdjustTexSize(Width:Int Var, Height:Int Var)
	Function Pow2Size:Int(N:Int)
		Local Size:Int

		Size = 1
		While Size < N
			Size = Size Shl 1
		Wend

		Return Size
	End Function

	Width  = Pow2Size(Width)
	Height = Pow2Size(Height)
End Function

Function TexFromPixmap:Int(pixmap:TPixmap, mipmap:Int = True)
	If pixmap.format<>PF_RGBA8888 pixmap=pixmap.Convert( PF_RGBA8888 )
	Local width:Int=pixmap.width,height:Int=pixmap.height
	AdjustTexSize width,height
	If width<>pixmap.width Or height<>pixmap.height pixmap=ResizePixmap( pixmap,width,height )
	
	Local old_name:Int,old_row_len:Int
	glGetIntegerv GL_TEXTURE_BINDING_2D,Varptr old_name
	glGetIntegerv GL_UNPACK_ROW_LENGTH,Varptr old_row_len

	Local Name:Int
	glGenTextures 1,Varptr name
	glBindtexture GL_TEXTURE_2D,name
	
	Local mip_level:Int
	Repeat
		glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
		glTexImage2D(GL_TEXTURE_2D, mip_level, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixmap.Pixels)
		If Not mipmap Exit
		If width=1 And height=1 Exit
		If width>1 width:/2
		If height>1 height:/2
		pixmap=ResizePixmap( pixmap,width,height )
		mip_level:+1
	Forever
	
	glBindTexture GL_TEXTURE_2D,old_name
	glPixelStorei GL_UNPACK_ROW_LENGTH,old_row_len

	Return name
End Function


Cheers
Charlie


JoshK(Posted 2011) [#3]
glPixelStorei GL_PACK_ROW_LENGTH,width
glPixelStorei GL_UNPACK_ROW_LENGTH,width

Last edited 2011


*(Posted 2011) [#4]
Thanks guys i will have a look


*(Posted 2011) [#5]
@jkrankie: thanks it works a treat :)

@JoskK: thanks for the help that too is very useful to know :), being still a novice to intermediate in the world of OpenGL its a learning experience.


*(Posted 2011) [#6]
@jkrankie: does your loader have a problem with pngs with alpha channel? The reason i ask is they all seem to come in as blocks of black ? I will have a look and see if there is something missing :)


jkrankie(Posted 2011) [#7]
Shouldn't do. It works here at least. Are you sure you've saved your pngs correctly?

Either way, this may help...

Function ApplyAlpha:TPixmap(pixmap:TPixmap) NoDebug
	
	Local tmp:TPixmap=pixmap
		If tmp.format<>PF_RGBA8888 tmp=tmp.Convert( PF_RGBA8888 )
		
		Local out:TPixmap=CreatePixmap( tmp.width,tmp.height,PF_RGBA8888 )
		'Return out
		For Local y:Int = 0 Until pixmap.Height
			Local t:Byte Ptr=tmp.PixelPtr( 0,y )
			Local o:Byte Ptr=out.PixelPtr( 0,y )
			For Local x:Int = 0 Until pixmap.Width

				o[0]=t[0]
				o[1]=t[1]
				o[2]=t[2]
				o[3] =t[3]' (o[0] + o[1] + o[2]) / 4.0

				t:+4
				o:+4
			Next
		Next
		Return out
End Function


Can't remember who wrote it, or where it's from though.

Cheers
Charlie

Last edited 2011


*(Posted 2011) [#8]
@jkrankie: apologies I forgot to enable GL_BLEND :) all is working perfectly now although I have added masking to your texture loader :)

heres the code
Function TexFromPixmap:Int(pixmap:TPixmap, mipmap:Int = True)
	If pixmap.format<>PF_RGBA8888 pixmap=pixmap.Convert( PF_RGBA8888 )
	Local width:Int=pixmap.width
	Local height:Int=pixmap.height
	
	AdjustTexSize width,height
	If width<>pixmap.width Or height<>pixmap.height pixmap=ResizePixmap( pixmap,width,height )
	
	Local old_name:Int,old_row_len:Int
	glGetIntegerv GL_TEXTURE_BINDING_2D,Varptr old_name
	glGetIntegerv GL_UNPACK_ROW_LENGTH,Varptr old_row_len

	Local Name:Int
	glGenTextures 1,Varptr name
	glBindtexture GL_TEXTURE_2D,name
	
	Local CheckImage:Byte[ Width, Height, 4]
	Local Pixel:Int = 0

	'remove masked pixels (MaskActive is a byte, MaskRed, MaskGreen and MaskBlue are Int)
	If MaskActive = True
		For Local y:Int=Height-1 To 0 Step -1
			For Local x:Int=0 To Width-1
				Pixel = ReadPixel( pixmap, x, y )
				If ( Pixel &$FF = MaskRed And ( pixel Shr 8 ) &$FF = MaskGreen And ( Pixel Shr 16 ) &$FF = MaskBlue ) 
					WritePixel( pixmap, x, y, 0 )
				EndIf
			Next
		Next
	EndIf

'	Pixmap = ApplyAlpha( Pixmap )

	Local mip_level:Int
	Repeat
		glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
		glPixelStorei GL_PACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
		glTexImage2D GL_TEXTURE_2D, mip_level, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixmap.pixels
		If Not mipmap Exit
		If width=1 And height=1 Exit
		If width>1 width:/2
		If height>1 height:/2
		pixmap=ResizePixmap( pixmap,width,height )
		mip_level:+1
	Forever
	
	glBindTexture GL_TEXTURE_2D,old_name
	glPixelStorei GL_UNPACK_ROW_LENGTH,old_row_len

	Return name
End Function


Basically the MaskRed, MaskGreen and MaskBlue are the colour of the colour you want to remove and MaskActive is a True/False value if its active or not :)


Kryzon(Posted 2011) [#9]
Wouldn't it be best to implement the mask flag and mask color as optional parameters to this function?


*(Posted 2011) [#10]
The reason i done it like that was internally its used with global variables but i do see ya point :)