The '3D Engine' thread

BlitzMax Forums/OpenGL Module/The '3D Engine' thread

Tom(Posted 2005) [#1]
Hi all,

So is anyone working on a 3D Engine?

To my knowledge:
Cyanide is working on one (free AFAIK)
Antony is porting Vivid? (commercial)
Arkon has BasicGL (commercial & Win32 only for now)
BRL will sort something obviously (most likely commercial)
Terrabit sort of has one (I think? :) (free)
Noel Cower started then stopped on one (someone jump start that guy back into action!) (free AFAIK)

Any others in progress?

I'm trying to make one myself, progress is slow as I'm not finding GL that quick to learn, or at least, it doesn't seem as organised as DX and its documentation.

So far I have an entity system like Blitz3Ds, with local/parent/world translation/rotation commands, working hierarchy, a scene graph type render system, render tweening like Blitz3Ds.

The first thing I messed with when I got Max was GLSL / shaders, and I have a module almost ready to drop into this (shaders rock, and Mark agrees! :) Loading and using a shader can be as easy as 3 commands, and set/getting Uniform & Attribute variables in the shader is just as easy:

myShader.SetUI1("myUniformShaderVarName", value)

Anyways, I'm currently learning about multitexturing/meshes & mesh importers/rendering methods.

My target is for something at least of Blitz3Ds calibre (read as *ease of use!*) to start with, something that can be built upon by anyone.

Keep ya posted!
Tom
p.s HunterSD, they found the 11th commandment!! It reads 'Though shalt not free resources by thine self' :P


eizdealer(Posted 2005) [#2]
Hi Tom
How did you learn GLSL? Is there something like the Redbook or NeHe's tutorials?

I don't want to say I'm coding an engine, it's rather playing around a bit with OpenGL.
I've got Stencil shadows working as well as basic lighting, entity / camera / transformation (hey I had to learn about Quaternions) stuff. I'm working on Frustum Culling right now. What I'm aiming at is rather the opposite of your targets: I don't need it to be that easy (don't know whether I'll even release it to the public) but I want it to be as fast as possible.

Maybe we can support each other in this thread. If anybody needs help with Stencils shadows, Quaternions etc. I can try to help or paste some code.

Is there a way to render something faster than building Display Lists?
Would be nice if we had some OpenGL 'pros' helping us Newbies :)

Greetings, Daniel

Edit: A little example code extract:
Mesh = EEMLoader.LoadMesh("Meshes/floor.eeMesh")
Mesh.MergeVertices()
Mesh.UpdateNormals()
Mesh.BuildDisplayList()
Mesh.UpdateDimensions()
Bottom:eeEntity = eeEntity.Create(Mesh)

Bottom.Material = eeMaterial.Create()
Bottom.Material.Shininess = 0.3
Bottom.Material.Roughness = 0.0
Bottom.Material.LoadTexture("Textures/test.bmp")
Bottom.Position(-20,0,-20)



PaulJG(Posted 2005) [#3]
Yeap, I got one in the pipeline.. slow going though, and certainly not in the same league as some of those you mentioned above.

Still, thats all the fun of writing your own engine - improving and adding features as you learn them.


Tom(Posted 2005) [#4]
eizdealer: I've not learned the actual language yet, maybe just a little to mess about, I was talking more about how to easily integrate the whole GLSL system, and it's methods of setting & getting variables within the shader (as mark talked about in his latest worklog).

I find GL docs aint written in 'Plain Jane' English :) They seem all over the place to me. Today I've been reading up on extented multitexturing, and how you can (card support permitting) have awesome control of texture blending. The ARB text docs don't explain stuff well, very techy, but now I've got it written down like this, it makes a little more sense to me.

A Texture Unit Type, idea being blending modes are set per texture unit, per surface, rather than per texture (I honestly don't knw if this will turn out to be a good or bad thing performance wise, time will tell!)

Good for advanced blend tweaking. For easier blending, you can always use regular blending, or just call some preset functions that do all this crap for you :)

	Field combineRGB:Int
	Field combineAlpha:Int
	'Defines how RGB & Alpha Inputs are Combined to produce the Output Color/Fragment
	'Accepts:
	' - GL_REPLACE						= Arg0
	' - GL_MODULATE <(Default) for RGB & Alpha		= Arg0 * Arg1
	' - GL_ADD						= Arg0 + Arg1
	' - GL_ADD_SIGNED_ARB					= Arg0 + Arg1 - 0.5
 	' - GL_INTERPOLATE_ARB					= Arg0 * Arg2 + Arg1 * (1-Arg2)
	' - GL_SUBTRACT_ARB					= Arg0 - Arg1


	Field source0RGB:Int
	Field source1RGB:Int
	Field source2RGB:Int
	Field source0Alpha:Int
	Field source1Alpha:Int
	Field source2Alpha:Int
	'Defines the Source Input colors for both RGB & Alpha (Arg0, Arg1 & Arg2)
	'Accepts:
	' - GL_TEXTURE<x>_ARB	<(Default for 0)	= The Texture Fragment Color from 'this' Texture
	' - GL_CONSTANT_ARB	<(Default for 2)	= Takes a Color from glColor(), or a Material Color (not 100% sure on this!)
	' - GL_PRIMARY_COLOR_ARB			= Color Array set with glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texColorArray[4])
	' - GL_PREVIOUS_ARB	<(Default for 1)	= The Texture Fragment Color from the Previous Texture


	Field operand0RGB:Int
	Field operand1RGB:Int
	Field operand2RGB:Int
	'Operands operate on the Source Colors, non-defaults could be used to Invert Source Inputs 
	'Accepts:
	' - GL_SRC_COLOR			<(Default for 0 and 1)
	' - GL_ONE_MINUS_SRC_COLOR
	' - GL_SRC_ALPHA			<(Default for 2)
	' - GL_ONE_MINUS_SRC_ALPHA


	Field operand0Alpha:Int
	Field operand1Alpha:Int
	Field operand2Alpha:Int	
	'Same as above, but affects Alpha
	'Accepts:
	' - GL_SRC_ALPHA			<(Default for 0, 1 and 2)
	' - GL_ONE_MINUS_SRC_ALPHA


	Field rgbScaleArb:Float
	Field alphaScale:Float
	'The Final output RGB & Alpha values for this Texture Unit can be Multiplied
	'by 1.0 = no effect/default, or 2.0 & 4.0.	Effectively a 'Modulate2x/4x' setting that brightens the texture
	'Accepts:
	' - 1.0
	' - 2.0
	' - 4.0
	
	Function Create:tUnit(unit:Int)
		Local t:tUnit = New tUnit
		
		t.combineRGB		= GL_MODULATE
		t.combineAlpha		= GL_MODULATE
		
		t.source0RGB 		= 33984 + unit
		t.source1RGB		= GL_PREVIOUS_ARB
		t.source2RGB		= GL_CONSTANT_ARB

		t.source0Alpha		= 33984 + unit
		t.source1Alpha		= GL_PREVIOUS_ARB
		t.source2Alpha		= GL_CONSTANT_ARB		

		t.operand0RGB		= GL_SRC_COLOR
		t.operand1RGB		= GL_SRC_COLOR
		t.operand2RGB		= GL_SRC_ALPHA

		t.operand0Alpha	= GL_SRC_ALPHA
		t.operand1Alpha	= GL_SRC_ALPHA
		t.operand2Alpha	= GL_SRC_ALPHA

		t.rgbScaleArb		= 1.0
		t.alphaScale		= 1.0
		
		Return t
	End function


Pretty understandable right? If not, go look up the ARB docs on gl_arb_tex_env_combine....come back, and say 'yup...' :)

Tom


eizdealer(Posted 2005) [#5]
What would be the best and fastest way to render a terrain without LOD whose tiles are given as well as the view frustum planes and the camera position / range?

I thought about doing some kind of Quadtree, then putting all the data of the visible Quads into an array and finally rendering it with glDrawArrays or a command alike. But I guess there would be a lot of overhead when compiling from visible Quads to the array. Is there a better way to do it?
Maybe just checking rather large Quads (e.g. 16x16 tiles) that are close to the camera and not subdivide, just draw them?
The camera position would be similar to a top-down RTS game, if this may help. How do 'professional' RTS games do the culling?


Kalakian(Posted 2005) [#6]
Is this a 3D rts game? Seems to me you'd want an octree or BSP tree if its in 3D, or you'll be missing a dimension :D

I think BSP is supposed to be more optimal than an octree, but I couldn't get my head around how to implement it when I first looked at it - maybe something for me to go back to at some point. If you can implement a quadtree, I'm sure you'd have no problem with an octree, just add in an extra 4 branches and use a set minimum number of polygons for subdivision.

Dunno if I've helped any there, so let me know if I have, or if I'm just talking jibberish :D


Tom(Posted 2005) [#7]
regarding the term Quads, in B3D talk that would be 2 triangles, but of course in GL you can render real quad polygons.

I'm just experimenting with vertex arrays and vertex buffer objects now. But I did ask some guys about whether using GL_QUADS was good or bad, and I was told that GL is optimized for using GL_TRIANGLES.

Just something to bear in mind when rendering.


dmoc(Posted 2005) [#8]
I switched to quads in my app and have not noticed a difference. Maybe the driver does the conversion but at least it's simpler for me to work with quads for the most part. One thing to watch out for though is non-planer quads, ie, verts of a triangle form a plane but the same may not be true of a quad. Though not a prob if driver do actual split quads into tri's as part of optimisation.


poopla(Posted 2005) [#9]
Havn't read the discussion but triangle strips are the most optimized rendering method via GL.


N(Posted 2005) [#10]
(someone jump start that guy back into action!)


I'm working on another, just no API abstraction this time around. It's too much of a hassle in BlitzMax.

Not gonna do anything particularly advanced either- that would be major overkill.


Chris C(Posted 2005) [#11]
I'm using ODE, which has been *so* useful and not just
for dynamic physics!

The collision system (one thing I didnt want the nightmare
of coding) is absolutly top notch.

having geoms about that aren't involved in physics, but
do collide, seems to be quite efficient for static mesh's

Theres some useful math helper routines too

Short of terrain culling and special graphics effects
it leaves you with a lot of the tedious work done...

It would be really nice to see a community project along
these lines, but I fear that such an engine might get
so overloaded with features that it will crawl.

Whats needed is somthing simple and lightweight...

$0.02


eizdealer(Posted 2005) [#12]
Tom:
Could you give a small example of how to use and integrate GLSL? I have absolutely no idea of GLSL.
What are Vertex Buffers and how can you use them in BMax?

Kalakian:
I think a QuadTree should be enough for a 3D RTS, because when a tile is visible, usually all objects over this tile are visible as well. I was just wondering about whether it's fast enough to compile visible Quads (by the way I was talking about 'Quads' as part of a Quadtree, nothing you could render) into an array.
What exactly is the advantage of a BSP Tree compared to a QuadTree?


Does anyone know whether glVertex3s is faster than glVertex3f because theoretically you send only half of the Bytes to the graphics card. Of course the Fill Rate is not faster but maybe you could save some nano seconds this way 8)


Kalakian(Posted 2005) [#13]
Yeah, my mistake, I was just thinking generic 3D game there, so no real need for an octree instead of a quadtree.

As for the advantage of using a BSP, I'm not entirely sure. I know its supposed to be more efficient than an octree, but I don't really know how it would compare to a quadtree.

I think your idea of using the quadtree to decide what tiles of the terrain were to be rendered should be efficient enough for an RTS. I would suggest subdivision of the quads though if you're going to draw everything above the tile, but the advantages of this would really depend on what camera angles you would allow. If, as you implied in your earlier post, the camera was static semi-topdown, I think just using an array to store the tiles would probably be optimal. Then, you could simply use the distance formula to check if the tile is within a certain radius away from the point where the camera's lookat vector crosses the terrain. If it is, render it, if not, don't

Thats my opinion anyway, whether its useful or not is an entirely different matter ;)


Damien Sturdy(Posted 2005) [#14]
I had started one based on Terrabits code. I added more blitz3d compatible commands but got stuck on parenting and such, so decided it was too advanced for me and gave up... :/


AdrianT(Posted 2005) [#15]
oh yeah, forgot about this thread. I posted a little showcase entry with some early trinity blizmax engine video clips at:

http://www.blitzbasic.com/Community/posts.php?topic=43408

pretty early but I thought you guys might be interested to see how trinity is coming along.


eizdealer(Posted 2005) [#16]
Hey there again!
I got stuck with the terrain, when it comes to Frustum Culling. Actually it works well, but there are some tiles that don't get clipped although it's obvious that they're out of the view frustum.
I think it has something to do with the formula I'm using for detection whether a tile is in view or not. It's the 'common' CubeInFrustum formula that is described in all Frustum Culling tutorials. It checks whether all points of a cube are behind one of the clipping planes. If so, it can't be visible. But in some cases this detection failes. Usually this should be no problem at all, but in this case it's quite a lot tiles that would be drawn this way.
A little screenshot (blue = as visible detected tiles, yellow = eye), should be self-explaining:
[This was an image]
Any ideas?

Edit:
OK, I got it working now. The problem was in the CubeInFrustum formula - I had to add some stuff (and that was wrong *g*).


eizdealer(Posted 2005) [#17]
OK, new post new problem.
The Quadtree works very well now, it lists Quads that are inside the view volume. Each of these Quads is made up of several terrain tiles. I'm looping through every Quad and then through every terrain tile of that Quad to render the tile with glbegin etc. right now (just to see whether it works). The problem with that is of course the speed (although it's resulting in ~400 FPS with a relatively large terrain, which is surprisingly fast).

My first idea was to use Vertex Arrays of course - compile all terrain tiles into an array, then draw that array. This should work OK with one terrain texture. But what if you want to have the possibility to have different textures on the terrain? How could you avoid the sharp edges between different textures and let them fade out smoothly?

I think a good solution is to assign a texture to each terrain vertex and then blend the texture over the tile, if the tile's other vertices have different textures. A little example picture, these are two terrain tiles, the circles at the edge vertices show the 'texture' (in this case it's just a color), the first tile has blending enabled, because its vertices have different textures, the second tile has blending disabled:


To get to the actual problem: How do I combine this blending technique and the terrain rendering efficiently?
I thought a good way was pushing all vertex coordinates, vertex texture coordinates and vertex normals to the graphics card using glVertexPointer etc., saving indices and then figuring out which indices need to be drawn for each texture. First without blending (solid base tiles so to say) then blended tiles. But what's the fastest way to do it? I've been trying for hours now with different approaches but I just don't get it working. Couldn't find a tutorial that covers this either. The tutorials always explain how a Quadtree works and stuff but never this part :/

Anybody has any ideas? Or does this sound completely stupid (English is not my native language and I often have problems to express myself about complex coding stuff like this even in my native language...)?
Thank you for reading by the way ;)


jfk EO-11110(Posted 2005) [#18]
Any news from the front?


TeraBit(Posted 2005) [#19]
My one was a 'Get you started' one that doesn't work too well on the Mac yet.

Anyone wanting to play can get it Here

Works lovely on the PC, needs a Mac man to look at why it doesn't *quite* work on the Mac.


Smurfpuss(Posted 2005) [#20]
Thanks TeraBit it was great help im currently working on my own i can't wait for mark any more any one know where i can finde something about opengl terrain more then nehe ?


jfk EO-11110(Posted 2005) [#21]
thanks - how about under linux on x86?


Smurfpuss(Posted 2005) [#22]
Well i have played around a lot with opengl now and i found it great like people woulde really need to start a opengl3d engine prodject like where we all start at the base and add more and more a open source prodject like
some one write the function start!
ex

InitGL()
positioncam()

well this is just stuppid idea but i coulde be great or every one coulde add more to Terabits engine
i have tryide but can't really finde out how to add key strokes so you can move camera!


N(Posted 2005) [#23]
Smurfpuss: NO. No more community projects! Save us from the community projects!

On another note, how do you feel about me writing tutorials on engine programming for BlitzMax in the Blitz Newsletter?


Smurfpuss(Posted 2005) [#24]
well sorry!
and no you don't need to write a tutorial on engine programming in the blitz Newsletter

Oki it was a bad idea so you don't need to be rude
and i will spare every one the talk about community prodjects!

:(

Like the unfriendly respons on this board is just bad
like not every one is great coders but we are trying to learn


jfk EO-11110(Posted 2005) [#25]
The idea wasn't that bad. If it happens spontanously, why not. I've seen a lot of spontanous Community projects that have been a success. Like Alien Breed or FLE.


Bot Builder(Posted 2005) [#26]
The fastest way of rendering is definitly not just triangle strips...

You can further optimize a series of gl calls to create an object by creating display lists. These basically run all your gl commands through the driver and store the raw output so that all you need to do is passthis data to the card, skipping the translation phase. This only works well with static geo.

Nearly as fast as display lists, but less versatile in some ways are Vertex arrays. The primary benifit is you can modify vertices very quickly. You create a few arrays storing position, color, uvs, etc, and pass pointers to them to gl. then you can modify the data in them, whatever each frame, and tell gl to bulk render the arrays. Still has to translate the instructions to hardware, but since its done in bulk its a ton better than calling a function for every vertex. A further enhancment is to use an index array which can decrease the amount of data sent by sharing vertices among the triangles, beating the number of shared vertices of strips or fans.

Using extensions it should also be possible to have vertex bufffers, basically arrays stored on the graphics card. In other words, crazy speed :)


Diordna(Posted 2005) [#27]
Er, wrong thread? Ignore this.


Rook Zimbabwe(Posted 2005) [#28]
Hmmm OK I see that OPenGL will be quite useful but I need to ask an ignorant question... Which engine will be DX9+ for BMAX??? Will any??? Are we (as a group) turning our backs on DX??? Did I miss a memo???


Rook Zimbabwe(Posted 2005) [#29]
Boy do I know how to kill a thread or what???


N(Posted 2005) [#30]
Sure do.

Snipped from my engine...


That comprises the core of the engine. Needs redesigning so the core has no association with entities though.