Loading textures -> slow!

BlitzMax Forums/BlitzMax OpenGL Programming/Loading textures -> slow!

hi!

just a question:
i am loading textures in my openGL engine by opening the image file and putting each texel into the bank like that:

Function LoadTexture(file$, flags = 0)
img = LoadImage(file$)
w = ImageWidth(img)
h = ImageHeight(img)
nw = GetWidth(w)
nh = GetWidth(h)
t.texture = New texture
t\bank = CreateBank(12)
t\w = nw / BLE_TextureQuality
t\h = nh / BLE_TextureQuality
t\sx# = 1
t\sy# = 1
bank_size = t\w * t\h * 3
bank_img = CreateBank(bank_size)
ib = ImageBuffer(img)
LockBuffer ib
For y = 0 To t\h - 1
	off = bank_size - (y + 1) * t\w * 3
	For x = 0 To t\w - 1
		rgb = ReadPixelFast(w * x * BLE_TextureQuality / nw, h * y * BLE_TextureQuality / nh, ib)
		PokeByte bank_img, off, (rgb And $FF0000) Shr 16
		PokeByte bank_img, off + 1, (rgb And $FF00) Shr 8
		PokeByte bank_img, off + 2, rgb And $FF
		off = off + 3
	Next
Next
UnlockBuffer ib
FreeImage img
glGenTextures 3, t\bank
glBindTexture GL_TEXTURE_2D, PeekInt(t\bank, 0)
glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST
glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST
glTexImage2D GL_TEXTURE_2D, 0, 3, t\w, t\h, 0, GL_RGB, GL_UNSIGNED_BYTE, bank_img
glBindTexture GL_TEXTURE_2D, PeekInt(t\bank, 4)
glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR
glTexImage2D GL_TEXTURE_2D, 0, 3, t\w, t\h, 0, GL_RGB, GL_UNSIGNED_BYTE, bank_img
glBindTexture GL_TEXTURE_2D, PeekInt(t\bank, 8)
glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR
gluBuild2DMipmaps GL_TEXTURE_2D, 3, t\w, t\h, GL_RGB, GL_UNSIGNED_BYTE, bank_img
FreeBank bank_img
Return Handle(t)
End Function


this is extremely slow because i am using ~20 textures about 512*512 on a little demo map. isn't there any way to make it work faster?

thanks.

Maybe this one could be usefull for you. It is the loadtexture
method off 'minib3d'.

Function LoadTexture:TTexture(file$,flags=1)
	
		If flags&128 Then Return LoadCubeMapTexture(file$,flags)
	
		Local tex:TTexture=New TTexture
		If FileType(file$)=0
			Repeat
				file$=Right$(file$,(Len(file$)-Instr(file$,"",1)))
			Until Instr(file$,"",1)=0
			Repeat
				file$=Right$(file$,(Len(file$)-Instr(file$,"/",1)))
			Until Instr(file$,"/",1)=0
			If FileType(file$)=0
				DebugLog "ERROR: Cannot find texture: "+file$
				Return Null
			EndIf
		EndIf
		
		' get absolute filename of texture - returned by TextureName$
		If Instr(file$,":")=False
			tex.file_abs$=CurrentDir$()+"/"+file$
		Else
			tex.file_abs$=file$
		EndIf
		tex.file_abs$=Replace$(tex.file_abs$,"","/")
		
		tex.file$=file$
		tex.flags=flags

		' combine specifieds flag with texture filter flags
		For Local filter:TTextureFilter=EachIn TTextureFilter.filter_list
			If Instr(file$,filter.text$) Then tex.flags=tex.flags|filter.flags
		Next
		
		' check if tex already exists
		Local tex_exists=False
		For Local tex2:TTexture=EachIn tex_list
			If tex.file$=tex2.file$ And tex.flags=tex2.flags
				tex_exists=True
				tex.pixmap=tex2.pixmap
				tex.gltex=tex2.gltex
			EndIf
		Next
		
		' if tex doesn't already exist, load it and add to tex list
		If tex_exists=False
		
			tex.pixmap:TPixmap=LoadPixmap(file$)
			'tex.gltex=GLTexFromPixmap(tex.pix,True)
	
			Local mipmap=False
			If tex.flags&8 Then mipmap=True
			
			If tex.pixmap.format<>PF_RGBA8888 tex.pixmap=tex.pixmap.Convert( PF_RGBA8888 )
			Local width=tex.pixmap.width,height=tex.pixmap.height
			AdjustTexSize width,height
			If width<>tex.pixmap.width Or height<>tex.pixmap.height tex.pixmap=ResizePixmap( tex.pixmap,width,height )
	
			tex.width=width
			tex.height=height
			
			Local old_name,old_row_len
			glGetIntegerv GL_TEXTURE_BINDING_2D,Varptr old_name
			glGetIntegerv GL_UNPACK_ROW_LENGTH,Varptr old_row_len

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

			tex.gltex=name
			ListAddLast(tex_list,tex)
			
		EndIf
			
		Return tex
		
	End Function


nope, sorry. my problem is, that pushing each of the (256^2)*20 texels into data banks is very slow. even on debuger off.
a c++ library would be useful, but i don't know how. so i think i have to improve it in blitz.

You don't need to load image. Load image means loads the data into main memory, upload it to the graphics card as a texture, then you're also doing al lock image which then has to download the image from the graphics card and turn it into a pixmap, then you're doing additional processing on it.

Use LoadPixmap. Also do not use PokeByte or ReadPixelFast, use pointer and treat the data like an array e.g. Data[Offset]. If you use PokeByte for every pixel you are causing it to look up the bank object, read the bank's base pointer, you have to calculate x and y offsets turned into an address, and then access the pixel. Very slow. Just have a source pointer and dest pointer and read whole Int's at a time where possible and use binary operations to shift stuff around and get the values where you want them. To make it even faster you can load RAW graphics data directly into the bank, perhaps a line at a time if you need a modulo, which is faster yet then decompressing an image. I do that for 20 512x512 alpha channel images and it takes about a second to load.

oh well :0. i don't quite understand. is there a code snippet out there somewhere?
edit: oh and i am programming in bb, not bmx. is there still a way?

I do this by loading my own texture format straight into a pixelmap, then setting the gl texture pixels with this. I still haven't figured out how to store pixel data in the compressed format, and load the compressed data straight into OpenGL...it would be a lot faster.

i know. the stf format... it has the same size as your textures would have in bmp.

i tested it. 2 shorts for w/h in the file and then for each pixel 3 bytes in the texture format file. this is not very faster :(

edit: 9500 ms loading jpg. 6800 ms loading own texture format

Instead of reading a byte for each pixel, just copy the whole pixel data at once with ReadBytes().

neither slow.