Programming Game of life - Slow graphics

BlitzMax Forums/BlitzMax Beginners Area/Programming Game of life - Slow graphics

IcemanX(Posted 2015) [#1]
Hello all! This is my first post on the forums!

I've been working on an cellular automata (or falling sand game, if you prefer that)

It's working swell, but I notice I am losing A LOT of fps to the rendering. My current rendering process looks something like (rough example):

SetGraphicsDriver GLMax2DDriver()
glDisable GL_TEXTURE_2D
glBegin GL_POINTS

For i:cell = eachin cellgrid

i.update
i.render

next

glEnd
flip 0


and render looks like this:

method Render()

glColor4ub i.r, i.g, i.b
glVertex2i i.x , i.y

endmethod


I've read around on the forums and it seems that I should use gl_drawarrays, but I don't know how to use that to draw an array that is constantly changing. (Blank cells in the grid are null, and it seems openGL does not like this)

in a perfect world, I'd like the FPS problems to all be on the i.update part of the process, not the rendering. That way I can get to optimizing the cell checking code.

Any help would be appreciated, The hunt for FPS is driving me crazy!


col(Posted 2015) [#2]
Hiya,

Welcome to the forums!

As an unoptimised starting point would be that you can loop through the list and build up arrays of quads ( or points if you're rendering points )? I guess there may be more as to why its not working for you though.

edit:- if this case you may want to break up the rendering into 2 phases? a pre-render phase to prepare the array thats then given to the render phase to do its thing.


IcemanX(Posted 2015) [#3]
Thanks for the help Dave. I am rending as points, but only because I want to use as much "grid space" as possible.

As for the array, that is what I don't understand, How do I create an array of points and get it to draw where the cell is?

for example, if I were to setup a vertex and color pointer, and assuming I set the array to the size of the grid (width * height)

what would the code be to add a point to the array? The way opengl reads them out of the array (in order?) is very confusing.


col(Posted 2015) [#4]
Hey,

As with most things there are tons of different ways to get things done. With graphics you can have separate arrays for each 'component' of your vertex data ( this mean an array of vertices, another array for colors etc ) or you can pack the data into 1 single array, it's to you as a programmer to decide what best suits your problem case. For single packed arrays, at first it might be confusing with byte strides etc but it's really quite easy. I've just knocked up this code to hopefully help show how to setup a packed array of x,y,r,g,b vertex data and render it as points.


As an optimisation you would only change state when needed, that means that in this simple example you can put the glEnable... glVertexPointer and glColorPointer before the main loop and also move the glDisable... to after the Wend statement leaving just the glClear MangleVertices() glDrawArrays and Flip commands in the main loop.

edit: ps... as you have your data within types you would probably want to iterate through each instance and use an index counter to increment through the array, maybe instead of nulling an instance of a dead cell you could flag it as dead and not render or use it in an cell calculations, but use the instance as a chance to accurately increment the indexer?


IcemanX(Posted 2015) [#5]
Thank you VERY much Dave, that example is super helpful!

I have one more question. Is it possible to specify the vertices with Ints?

Or can someone explain the floats for positioning? I notice in your code the x and y can be set to a random float between -1.0 to 1.0, but how does that translate into the entire screen? is 1.0 the bottom of the screen and 0.5 or 0.0 the middle?

Thanks again for the help. I'm having trouble placing something at exactly the right spot. When I try to alter gldrawarrays for ints, it shows nothing on screen.


col(Posted 2015) [#6]
Hiya,

There are many coordinate systems used throughout the process of converting the coords of your defined vertices onto the screen - from 'model space' to 'world space' to 'perspective space' ( also called 'projective space' ) to 'screen space' etc, usually manipulated through matrix math or algebra.

Here, the -1 to +1 coordinate system is referred to as the 'normalized device coordinate' space and refers to the internal gpu device coordinate system. To use another coord space you can manipulate the vertice data yourself, or set up transform matrices to convert from one coord space to another, or set various parameters in gl and have it do some of the hard work for us :D Say for example you want to use screen space coords from 0 to 800 for the width and 0 to 600 for the height then ( gl has some convenient functions to help :) ) as you want 2d you can use the glOrtho function to change the projection matrix for us to map the screen space coords to the normalized device coord.

Also, my apologies if you tried to adjust the above example for experimenting as there is a bug in the offsetting used in the vertice setup function - that'll teach me for typing straight into the forum :-)

Here's the above example 'working as expected' for you to see the subtle differences...


There are a couple of things to note with the example. The vertices are still being setup as float values - the reason being is the OpenGL spec. The spec says that the vertex positions can be GL_SHORT, GL_INT, GL_FLOAT, or GL_DOUBLE, and that the color data can be either GL_UNSIGNED_BYTE or GL_FLOAT, and as the array is a float array for all components (xyrgb) then its easier to keep with that - just in this example. Don't forget that you can set up 2 arrays and use GL_INT for the vertice data and then use a byte array for the rgb color ( range from 0 to 255 for each r,g,b ), or even pack the rgb bytes into an integer if you really wanted to, the choice is all up to the programmer. My main reason I did the example that way is to show how to use a packed array and what the parameters actually mean and refer to.


IcemanX(Posted 2015) [#7]
I understand it mostly now. I could work with floats as they are just fine, If I could figure out the conversions for them.
It seems in your updated example, You've changed the matrix with glOrtho so that 800.0 (a float) would be equal to the right edge of the screen, right? I can understand and work with that.

Now how would one go about converting a 0-255 RGB value to the 0-1.0 floats?

Edit: I COULD just do this: [color]/255 = [glfloatcolor] that would work so that 255/255 = 1 and 0/255 = 0. Hmm.


col(Posted 2015) [#8]
Yep, the glOrtho call can be used to setup the projection matrix so that you can use vertex coordinates that directly relate to the screen coordinates.

And yes, doing a simple divide by 255 will work to scale the color value from 0.0 to 1.0, or alternatively, you could create another array of integers for the colors and use that when rendering.


IcemanX(Posted 2015) [#9]
I've got it all sorted now! Thanks a million Dave! Two things to note about your example:

1.glOrtho goes left,right edge,bottom, top edge. I noticed you had your glOrtho setup as if it would go in a logical order. :P Since blitzmax Defaults to top-left being 0,0 your glOrtho line should read:


glOrtho(0,width,height,0,-1.0,1.0)



In my opinion, it's backwards, but that's how it is.

Secondly, the algorithm for the array is still...odd. If adjusted like this, it does not cover the entire screen (It should, right?):


	vertices[(y * widthpoints) + x*5] = x
	vertices[(y * widthpoints) + x*5 + 1] = y
		
	vertices[(y * widthpoints) + x*5 + 2] = Rnd(0,1)
	vertices[(y * widthpoints) + x*5 + 3] = Rnd(0,1)
        vertices[(y * widthpoints) + x*5 + 4] = Rnd(0,1)



Also, as a side note: I've edited the code above where it WOULD cover the entire screen by using index numbers, but there are lines in my window CLEARLY not drawn, and this only appears to happen on AMD cards.

Anyone know anything about this?

here is a screenshot of something that WOULD cover the entire screen in a red box on Nvidia GPU, but running on AMD GPU. (Don't mind the edges, that's the editor window.)
http://prntscr.com/92xs8b


col(Posted 2015) [#10]
Ahh yes, OpenGL has 0,0 as the bottom left of the display. I'm more of a DirectX guy really but they're very similar in function just the syntax are different.

The algo above in the example that I wrote will color a pixel every other 5 pixels.
This colors every pixel and will obviously be slower due to more pixels and the speed will be cpu and gpu dependant ( until you summon up the courage to use compute shaders upon which it will be really really fast but will require a newer gpu :O) - but one step at a time )
Also 'order of precedence' was taking over in the algo positions.



I've tested the output using an nvidia and amd gpu ( i have both in this laptop ) and it looks ok here.