single surface rendering?

BlitzMax Forums/OpenGL Module/single surface rendering?

Nate the Great(Posted 2010) [#1]
Hi, I need to be able to render 50,000+ particles on a single surface, they should all be pretty simple untextured circles but I have no idea how open gl works and I cant seem to find any good place to start. Can anyone point me to a good starting place. I tried this but I know i must be missing something. I also didnt know if glpoints are faster than a single surface method. Sorry about my cluelessness.

Function rendergl()
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
	
	glPointSize(r)
	
	glBegin(GL_POINTS)
	For Local i:Int = 0 To num
        Local c# = .1 * pointlist[i].rho
        Local x# = 20 * Abs(pointlist[i].vx)
        Local y# = 20 * Abs(pointlist[i].vy)
        
		glColor3f(.3+x,.3+y,c)
		glVertex2f(pointlist[i].x, pointlist[i].y)
	Next	
	glEnd()
	Flip 'flip buffers???
End Function


I am also using this at the begining. I fear I am missing something big

SetGraphicsDriver(GLGraphicsDriver())

GLGraphics 1024,768,0,60




ImaginaryHuman(Posted 2010) [#2]
I was looking at your code and it all looks fine... then it occurred to me... GLGraphicsDriver does not do any OpenGL setup. If you switch it to GLMax2DDriver I bet it will work.

The GLGraphicsDriver gives you an OpenGL context but it hasn't set up any viewport, projection matrix, or any other GL `state`. So effectively it isn't even possible to draw anything to the screen at that point. You'd need to at least set up a projection e.g. glOrtho2D() or glOrtho() (forget which) and glViewport(), before you'd be able to see anything.

Secondly, 50000 sprites is a lot for an average computer. I know on my iMac I can do maybe 10-15000 at 60Hz... sprites maybe 32x32 or so.

To do texturing you need to set up a bunch of other stuff, too. You have to set up the whole `texture environment`, do the texture loading, switch texturing on, define the texture coordinates, etc.

You should look at using vertex arrays also, they can be up to twice the speed of the immediate-mode code you're using. Also consider display lists which are also faster. But to do this stuff you're going to have to learn quite a bit more OpenGL code.

Using GL_POINTS you can draw circles with a given point size, you're doing it correctly, provided the graphics driver supports points as large as you're trying to draw. You might also find the points render as squares unless you switch on glEnable(GL_POINT_SMOOTH). It also might not support point sizes less than 1.

And In OpenGL they're not called surfaces they're called textures ;D


Nate the Great(Posted 2010) [#3]
thanks IH, that was informative.

And I only need to use a single texture for them and I know switching textures can cause slowdown so maybe the 15000 can be bumped up a notch... I am really only shooting for 30 hz with sprites about 8x8 or 4x4

Do you know where I can find some tutorials for gl in bmax? I mean where do people learn all of this stuff?


TWH(Posted 2010) [#4]
Most people learn OpenGL from the NeHE tutorials, allthough they use old, deprecated OpenGL, they are popular. The NeHe's use glBegin/glEnd and the matrixes in OpenGL. The new way to do it is to use VBO's to store vertex data, shaders to render and a matrix library to do the transformations instead of glLoadMatrixf, glMultMatrixf and the Matrix stack (push/pop).

The Nehe tuts have all been ported to BlitzMax here: http://www.blitzbasic.com/Community/posts.php?topic=41689

But, if you know a little about C and pointers in BMax you should be able to figure out how any C/C++ OpenGL code can be written in Bmax.

Here's some C/C++ examples of "modern" OpenGL 3.0 use:
http://nopper.tv/index.html

Joe Groff @ Durian software has written a very good introduction on how to do the modern all-shader approach here:
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html

If you want to se what shaders are all about you can try them out in an editor like Ati Rendermonkey (big 100MB) or the simpler
ShaderMaker

or tigrous polydraw


You can mix old-fasioned OpenGL with shaders. This will probably be supported for a long time, but it isn't "pure" OpenGL 3.0+ The only problem with shaders is old cards (pre GeForce 4-5 and ATi 8500) and integrated intel chips don't support them. Or.. with the case of intel, don't always support them that well.

If you want to use fancy shader effects, but also want to run on low-end systems you might want to use the Nvidia Cg toolkit. It has a high-level shader language like GLSL, but you can compile to a variety of other formats, like oldfasioned assembly-style shaders that are more compatible with intel... and perhaps also Ati in some cases. ATi's cards/drivers are very picky about shader syntax. Just ask Taron about his AWSOME GLASS PONG GLSL experiment http://www.blitzmax.com/Community/posts.php?topic=88966#1011350

Nvidia has a lot of whitepapers and impressive stuff on OpenGL here.
http://developer.download.nvidia.com/SDK/9.5/Samples/samples.html

For instance on how to make a million particle system.... only problem is that you have to do it all on the GPU. You cant sett positions, velocity, color on cpu... that would require sending the data over the bus... :( .. maybe you could do it in batches... 10.000 at a time. Then they live on the gpu for some time going in a certain direction, or following a flowmap..
http://www.2ld.de/gdc2004/

Last year I started a particle system that was never finished... Maybe you find some of it useful. It sets texture state once and then draws lots of particles with different colors,positions,velocities.

Check TParticleSystem.doUpdate(p:TParticle) on how it sets various drawing methods (Bmax Drawimage, QUADS, GL_POINT...)

It uses glBegin/glEnd for bmax drawimage, tristrip.. but not quads or point sprites so they are fast.

It could be made a lot faster by using glArrays or VBO's I think. Perhaps also the texture could be done away with if it is rendered by a shader instead.

Instructions:
Click to place a 1000 particles at a time. Press the blue-square button to select render mode:



Nate the Great(Posted 2010) [#5]
well I only have gl 2.0, is there a way to upgrade? (I know nothing about graphics drivers)

I was able to get 100,000 particles at 30 fps whith your program. I really need a method to render fluid particles for my physics engine but maybe it is a good idea to do the particle rendering and physics on the gpu since its just sittin there doing nothing while the cpu does everything at the moment...


Nate the Great(Posted 2010) [#6]
ok great examples but ultimately I am a horrible gl programmer ;)

here is the render function

Function render()
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
	
	glEnable GL_POINT_SPRITE
	glTexEnvi GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE 
	glPointSize r
	glBegin GL_POINTS

	For Local i:Int = 0 To num
        Local c# = .1 * pointlist[i].rho
        Local x# = 20 * Abs(pointlist[i].vx)
        Local y# = 20 * Abs(pointlist[i].vy)
        
		glColor3f(.3+x,.3+y,c)
		glVertex2f(pointlist[i].x, pointlist[i].y)
	Next	
	glDisable GL_POINT_SPRITE
	glEnd()
	Flip 'flip buffers???
End Function


and before it I do

SetGraphicsDriver GLMax2DDriver()
GLGraphics 1024,768,0,60


I combined yalls advice/program code snippets/nehe tutorials but it still doesnt work... I still think I am doing something stupid, sorry for being such a noob at this haha


TWH(Posted 2010) [#7]
If you use GLGraphics you have to set up projection.. edit: The standard BlitzMax Graphics 1024,768',0,60 does' this for you. In the glMax2D driver ResetGLContext it does this:
		glDisable GL_TEXTURE_2D
		glMatrixMode GL_PROJECTION
		glLoadIdentity
		glOrtho 0,gw,gh,0,-1,1
		glMatrixMode GL_MODELVIEW
		glLoadIdentity
		glViewport 0,0,gw,gh


Edit. Here's a simple example of using GLGraphics... but for simplicity I guess you might aswell use Graphics. Then you dont have to mess with opengl projection and modelview matrices.

If you want to learn about the 2 important OpenGL matrixes
*GL_PROJECTION
*GL_MODELVIEW
*there is also a GL_TEXTURE matrix for translating textures about and projecting them onto this for effects like shadowmaps.
you can check out SongHpo.ca's article

and Nate Robins' OpenGL tutors




Nate the Great(Posted 2010) [#8]
ok thank TWH! it worked!


TWH(Posted 2010) [#9]
Great! Two more things! Errors and extensions! OpenGL has an error report mechanism with glGetError(), when debugging you should check for errors at least every frame. You can check after every opengl call if you suspect a certain call that went wrong. Perhaps do an if glGetError<> GL_NO_ERROR then debugstop()

Each time you call glGetError you remove an error code.

The are a few error codes. See code below. They are like booleans that are flipped on/off. So.. even if you really have 10 invalid enum errors, you only get one.

Other GL stuff like Framebuffer objects and GLSL shaders have error logging of their own. Like when you compile a shader or put together a FBO.

If you have multiple errors in a frame you should remove them all. That is, call glGetError until you get GL_NO_ERROR.

On the previous code I posted I got an invalid enum error each frame because there is no glDisable GL_POINT_SPRITE... in OpenGL 1.0 !!

You have to use Glew or some other way of initializing extensions. In blitzmax its as easy as glewInit()

If(GL_POINT_SPRITE)
Print "GL_POINT_SPRITE is supported"
glEnable(GL_POINT_SPRITE)
Else
Print "GL_POINT_SPRITE is Not supported"
EndIf

So. Before flip-ing you could check for errors like this:
		?debug
		Local errorCode:Int = glGetError()
		If errorCode = GL_NO_ERROR
			'all ok
		Else
			Print "GL ERROR!"
			If errorCode = GL_INVALID_ENUM Print "invalid enum"
			If errorCode = GL_INVALID_VALUE Print "invalid value"
			If errorCode = GL_INVALID_OPERATION Print "invalid operation"
			If errorCode = GL_STACK_OVERFLOW Print "stack overflow"
			If errorCode = GL_STACK_UNDERFLOW Print "stack underflow"
			If errorCode = GL_OUT_OF_MEMORY Print "GL_OUT_OF_MEMORY"
			If errorCode = GL_TABLE_TOO_LARGE Print "GL_TABLE_TOO_LARGE"
		EndIf
		?
		Flip



Nate the Great(Posted 2010) [#10]
I certainly need to favorite this thread so I can come back and see how to do opengl! This was very helpful, thanks!


TWH(Posted 2010) [#11]
Hehe. Great. I've made something new. Well. Ported an evaldraw script (magfield.kc) to Bmax and added alpha-blended particle lines:

This way to draw lines has some problems... Its hard to make the lines sharp. Im going to try drawing GL_LINES instead and running a glow filter on the screen in GLSL next.






Nate the Great(Posted 2010) [#12]
ok so now I am wondering how I can render at least 10,000 fuzzy dots or fuzzy dot images and then do a threshold filter that will give them a defined border... I am hopeful that this is all possible in pure bmax gl without the use of shaders so how would I render a fuzzy image 10,000 times efficiently? I am working my way through the code above but it is a bit over my head...


Howitzer(Posted 2010) [#13]
Hey Nathan, this is Christian from the VRC. I can't really help ya, just dropping in to say hi.