glTexImage2D For Each Texture draw?

BlitzMax Forums/OpenGL Module/glTexImage2D For Each Texture draw?

BLaBZ(Posted 2012) [#1]
Do I have to call glTexImage2D everytime I want to render a textured mesh?

Is there someway to store the mesh in video memory for faster draw calls?


SystemError51(Posted 2012) [#2]
Nope - you only have to bind an existing texture (think of it as something like "select" your texture).

glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, Textures[0])



This is from my engine, used to add an image into an array of selectable textures:

Local teximage:TPixmap = LoadPixmap(file) 
' Two conversions - RGBA and flip
teximage = ConvertPixmap(teximage , PF_RGBA8888) 
teximage = YFlipPixmap(teximage) 

' We can now process the data and create a texture
glGenTextures(1 , Varptr RT_Textures[RT_NextTexture]) 

glBindTexture(GL_TEXTURE_2D, RT_Textures[RT_NextTexture])

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_NEAREST) 

gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, teximage.width,teximage.height, GL_RGBA, GL_UNSIGNED_BYTE, texImage.pixels)
	
' Release the image
teximage = Null



Is there someway to store the mesh in video memory for faster draw calls?


Not really. A mesh really is just a large array of vertex coordinates. You'll have to keep those in RAM yourself, and iterate them on every frame.

Last edited 2012


Noobody(Posted 2012) [#3]
Do I have to call glTexImage2D everytime I want to render a textured mesh?

No. glTexImage2D allocates space for the texture and fills it with data from a buffer in RAM if you specify one. Once the texture is allocated, there's no need to call this function again (except if your source data changes, of course).


Is there someway to store the mesh in video memory for faster draw calls?

There are two ways, actually. You can either do it with display lists (which are outdated) or with VBOs (vertex buffer objects).

Display lists will "save" a series of OpenGL commands (including glVertex), compile it into an efficient format and store it in graphics card memory. You can then draw this display list an arbitrary number of times.

VBOs, on the other hand, allow you to allocate a buffer in video memory, copy into it, modify it and draw from it. What you actually store in this buffer is completely up to you; you can arbitrarily choose vertex attributes, vertex format, ordering of data etc.

The advantage to display lists is that they're extremely easy to use. glGenLists once, glNewList before your mesh rendering code and glEndList after it plus a glCallList in your main loop every time you want to draw it is literally all it takes.
The disadvantage though is that display lists are very rigid once they're compiled. Changing a command inside the display list means pretty much recreating and recompiling it, which is a costly process - not something you'd want in your main loop :)

The advantage to VBOs is that they're extremely flexible. They pretty much allow you to write arbitrary data to video memory and tell the GPU what to do with it. VBOs allow you to update subsections of it, either through copying a buffer from RAM or actually writing to video memory yourself through a pointer. Modifying a VBO is cheap.
The disadvantage is that it takes some time to get them to work - there's a lot to learn and mistakes are easily made. If you want, I can post my VBO utility classes that I use a lot.


SystemError51(Posted 2012) [#4]
Hey Noobody,

I just read up on the subject of display lists and was quite happy with that functionality (although I would have had to rewrite parts of my engine) - but I quickly learned that apparently, they are deprecated.

So I moved on the check up on VBO's, and it says on that OpenGL page

Warning: This article or section describes material that has been deprecated in OpenGL 3.0, and removed in core GL 3.1 and above implementations. It is recommended that you not use this functionality in your programs.


:(

Damn

Last edited 2012


BLaBZ(Posted 2012) [#5]
I thought I just needed glBindTexture but I keep getting this strange effect. It's selecting the image just not displaying it correctly



Last edited 2012


Noobody(Posted 2012) [#6]
@BLaBZ: From just the screenshot it's hard to tell what's going wrong. Try putting a Print(glGetError()) after each suspicious function call to find out whether one of them goes wrong.
Could you post your code so we can take a look?

@SystemError51: OpenGL 3.0 is a complete rewrite of the API. Many features (such as glBegin/glEnd, display lists) will not work in versions > 3.1.

VBOs however are still present in 3.0 (in fact, they're one of the central features since they're the only way to draw geometry) - it's just that some of the functions described on that OpenGL page are not.

General functions to create and modify a VBO are still safe, however, all glXXXPointer functions are deprecated as of OpenGL 3.0. The reason is that the entire fixed function pipeline has been removed and replaced by a completely programmable pipeline.
If you plan to be compatible with version 3.0 and greater, you have to use glVertexAttribPointer instead to define generic vertex attributes and write a custom vertex shader for your meshes that interprets these vertex attributes and handles them correctly.

It should be noted that deprecated functionality is still going to be supported for a long time to come, since legacy applications rely heavily on the fixed function pipeline.
However, older versions are unlikely to see new features, so if you can't do without tesselation or newer shader models, you'd probably be safer learning the new way of doing OpenGL.


BLaBZ(Posted 2012) [#7]
This is my initialize function


Method Initialize()

		glPixelStorei(GL_UNPACK_ALIGNMENT,1)
		glGenTextures(1, Varptr Texname)
		glBindTexture(GL_TEXTURE_2D, Texname)
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
		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, GL_RGBA,  TextureImage.Width,  TextureImage.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, TextureImage.Pixels)		
		

		glEnable(GL_TEXTURE_2D)											' Enable Texture Mapping
		glShadeModel(GL_SMOOTH)											' Enable Smooth Shading
		glClearColor(0.0, 0.0, 0.0, 0.0)									' Black Background
		glClearDepth(1.0)													' Depth Buffer Setup
		glDisable(GL_DEPTH_TEST)											' Disable Depth Testing
		glEnable(GL_BLEND)												' Enable Blending
		glBlendFunc(GL_SRC_ALPHA,GL_ONE)									' Type Of Blending To Perform
		glDepthFunc(GL_LEQUAL)												' The Type Of Depth Testing To Do
		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)					' Really Nice Perspective Calculations
		glHint(GL_POINT_SMOOTH_HINT,GL_NICEST)								' Really Nice Point Smoothing
		glBindTexture(GL_TEXTURE_2D,Texname)								' Select Our Texture
		glMatrixMode(GL_MODELVIEW)

		
	End Method



This is my update/draw function

glDisable(GL_LIGHTING)	
			
		glEnable(GL_TEXTURE_2D)
		glBindTexture(GL_TEXTURE_2D, Self.System.Texname)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Self.System.TextureImage.Width, Self.System.TextureImage.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Self.System.TextureImage.Pixels)
		
	  	

		glEnable(GL_BLEND)	
		
		For Local Particle:TParticle = EachIn Particles
			
			glMatrixMode(GL_MODELVIEW)
														' Enable Blending
			'glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA)
			Local modelView:Float[16]
		
			glPushMatrix
			
			glGetFloatv(GL_MODELVIEW_MATRIX,modelView)
		
			For Local i:Int = 0 To 2 
				For Local j:Int = 0 To 2
					If i = j
						modelview[i*4+j] = 1.0
					Else
						modelview[i*4+j] = 0.0
					EndIf 
				Next
			Next
	
			'Self.System.Initialize()
	
			glLoadMatrixf(modelView)
			
			'glLoadIdentity
			glTranslatef Particle.x,Particle.y,Particle.z

			'glColor3f 1.0,0.0,0.0
			glColor4f 0.2,0.2,0.2,Particle.Alpha
			glRotatef Particle.Rotation, 0.0,0.0,1.0
			glBegin(GL_TRIANGLE_STRIP)										' Build Quad From A Triangle Strip
				glTexCoord2f(1,1); glVertex3f(Particle.size,Particle.size,0)					' Top Right
				glTexCoord2f(0,1); glVertex3f(-Particle.size,Particle.size,0)					' Top Left
				glTexCoord2f(1,0); glVertex3f(Particle.size,-Particle.size,0)					' Bottom Right
				glTexCoord2f(0,0); glVertex3f(-Particle.size,-Particle.size,0)					' Bottom Left
			glEnd()	

			glPopMatrix
		Next




It should probably be noted that I'm using minib3d alongside this.