single surface rendering?
BlitzMax Forums/OpenGL Module/single surface rendering?
| ||
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 |
| ||
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 |
| ||
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? |
| ||
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: |
| ||
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... |
| ||
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 |
| ||
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 |
| ||
ok thank TWH! it worked! |
| ||
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 |
| ||
I certainly need to favorite this thread so I can come back and see how to do opengl! This was very helpful, thanks! |
| ||
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. ![]() |
| ||
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... |
| ||
Hey Nathan, this is Christian from the VRC. I can't really help ya, just dropping in to say hi. |