.

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

.

Post by Spintz »

Last edited by Spintz on Mon Dec 10, 2007 2:03 pm, edited 1 time in total.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Last edited by Spintz on Mon Dec 10, 2007 2:03 pm, edited 1 time in total.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Last edited by Spintz on Mon Dec 10, 2007 2:03 pm, edited 1 time in total.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

very useful as always, thanks for posting :)

I take it ESNRP_SOLID2 and ESNRP_TRANSPARENT2 are for 2-layer materials?
What happens to nodes which contain more than one material? Like for example if I have a lightmapped model with glass windows, does it still get rendered in the transparent pass and solid2, with the render part of the node splitting these up? this is also bad imo (not your doing, it's always been like that)


okay i might be talking out of the wrong end here, but since we're discussing major scene manager changes i'll throw in my own idea (python pseudocode)

Code: Select all

// node::OnAnimate - called on each node once per loop

// node::OnRegisterSceneNode - 
// 1) mesh buffers are split and added to render queue
// (node pointer needed for absolute transform and bounding box in light manager)
smgr.registerMesh(this, mesh) 

// or 2) node draws its self in specific render pass(es)
// for special nodes, like the text, shadow or billboard node
smgr.registerNode(this, ESNRP_SOLID | ESNRP_SHADOW)

// or 3) camera registers its self with a priority
// so the camera list can be sorted
smgr.registerCamera(this, priority)

// node::render
// only called on nodes that set draw manually, also cameras

// smgr::drawAll

onRegisterSceneNode() // register all visible nodes

cull check // all cameras vs all registered nodes

onAnimate(time, isCulled) // animators operate on culled nodes, but skinning is optional

// loop through each active camera
for camera in cameraList:
  // set render target, transform, and clip planes
  camera.render()

  // loop through all render passes
  for listOfThingsToRender in allPasses:

    // loop through all things to render in this pass
    for SThing in listOfThingsToRender:

      // render it if it isn't culled this pass
      // each thing in the render list stores what cameras it can be seen by
      if !SThing.isCulled[cameraNumber]:

        // if it is a mesh buffer
        if SThing.isBuffer:
          lightManager.setLights(SThing.bbox, SThing.transform, SThing.buffer.getMaterial())
          driver.setMaterial(SThing.buffer.getMaterial()) // usually the same 
          draw the buffer
        else:
          lightManager.setLights(SThing.node)
          SThing.node.render()
it doesn't account for multiple renders from the same camera.. i don't quite understand when someone would do this anyway.

flames/comments/suggestions appreciated
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Last edited by Spintz on Mon Dec 10, 2007 2:03 pm, edited 1 time in total.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

yes, I was thinking each camera has its own render targets, and the camera passes are rendered intermally by priority, the idea was that the rendering rules for passes are camera specific. i didn't put much thought into rendering from the same camera multiple times though. maybe its the wrong way to go about doing it.
basically the idea was to do a culling check against all cameras, and if none matched then 'isCulled' is set to false. SThing (either a mesh buffer or a node, didnt know what to call it) has a list of all cameras and whether it is visible in each one, so things can be skipped at each render time if they are culled.

for animation, i can see why animators would need to be called regardless (or they wont ever move when not visible), but skinning an animated mesh that is culled is a waste (very cpu hungry), which is why i thought of passing isCulled to the node.

as for registering meshes as well as nodes, say you have 100 meshes with 3 buffers (different texture in each buffer), you get 100 transformation changes and 300 texture changes.
if it split those into buffers and rendered them in turn, you'd get 300 transformation changes but only 3 texture changes.

I made a rather crude (and possibly unfair) test for this, the 6 peaks represent 100 to 2000 meshes for 1 to 6 textures in (steps of 100). excuse the crappy graphs, i havent figured out openoffice calc properly yet

ImageImage

Code: Select all

#if METHOD==1

				// method 1:

				// loop through meshes
				for (u32 currentMesh = 0; currentMesh < objectcount; ++currentMesh)
				{
					// set transform
					driver->setTransform(video::ETS_WORLD, m[currentMesh]);

					// loop through buffers
					for (u32 buffer=0; buffer < mesh->getMeshBufferCount(); ++buffer)
					{
						// set material
						driver->setMaterial(mesh->getMeshBuffer(buffer)->getMaterial());
						// draw buffer
						driver->drawMeshBuffer(mesh->getMeshBuffer(buffer));
					}
				}
#elif METHOD==2
				// method 2:
				// loop through buffers
				for (u32 buffer=0; buffer < mesh->getMeshBufferCount(); ++buffer)
				{
					for (u32 currentMesh = 0; currentMesh < objectcount; ++currentMesh)
					{
						// set material
						driver->setMaterial(mesh->getMeshBuffer(buffer));

						// set transform
						driver->setTransform(video::ETS_WORLD, m[currentMesh]);

						// draw buffer
						driver->drawMeshBuffer(mesh->getMeshBuffer(buffer));
					}
				}
#else
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Strong99
Admin
Posts: 687
Joined: Fri Mar 31, 2006 7:06 pm
Location: Netherlands
Contact:

Post by Strong99 »

So if you join them you could change the way things happen?
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

yes, if nodes registered a mesh (or meshes) to draw rather than registering themselves, then the buffers could be taken from each mesh, sorted by their material and texture and then rendered.
it also opens up the possibility of batching many buffers into one, which would also be pretty cool.. but it also makes things more complex.
there's probably lots of things i've missed, so please help tear the idea apart!

edit: hmm.. so what would be the best way to go about doing multiple passes then? IMaterialRenderer::getNumberOfPasses() or something? I've not played with multi-pass materials before, any shader guys have an opinion?
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Last edited by Spintz on Mon Dec 10, 2007 2:04 pm, edited 1 time in total.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

Yeah I know it wasn't an ideal test, just a quick mock up. I had an outdoor scene with a load of trees and plants in mind, I suppose it wouldn't offer any performance gain on an indoor scene where everything is part of a map, or where nodes only have one material (possibly even a significant loss).

edit: here's a worst case scenario, where the texture is changed every time as well as the transform (ignore the 1st texture since it doesnt change)
Image

Code: Select all

#else
				u32 rbuf=0;
				// test 3: texture changes every time
				// loop through buffers
				for (u32 buffer=0; buffer < mesh->getMeshBufferCount(); ++buffer)
				{

					for (u32 currentMesh = 0; currentMesh < objectcount; ++currentMesh)
					{

						if (++rbuf == mesh->getMeshBufferCount() )
							rbuf=0;

						// set material
						driver->setMaterial(mesh->getMeshBuffer(rbuf)->getMaterial());

						// set transform
						driver->setTransform(video::ETS_WORLD, m[currentMesh]);

						// draw buffer
						driver->drawMeshBuffer(mesh->getMeshBuffer(buffer));

					}
				}
#endif 
as for materials, CMeshSceneNode has a 'ReadOnlyMaterials' option which specifies if it should use the materials from the original mesh, or to set its own materials at render time.
However, this way gives us a nasty problem with CAnimatedMeshSceneNode, where the skinned mesh is held inside IAnimatedMesh rather than in the scene node, which means it needs to be skinned again in each render because there might be multiple nodes which share one AnimatedMesh. In this case the mesh data should be held in the node and have it pass its SMesh pointer to the AnimatedMesh for skinning, or at least there should be an option to do it this way.
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

If you want to split some hardware accelerated parts you should introduce a vertex buffer underneath the mesh buffer. That one could be uploaded to GPU and be shared among several mesh buffers. Mesh buffers are more abstract parts of the engine view, not to be mapped directly to hardware.
BTW: I split this discussion from the other thread to make it more visible.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Last edited by Spintz on Mon Dec 10, 2007 2:05 pm, edited 2 times in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

As opposed to indexed vertex lists which are pure geometry information which makes one side of the render information. The other one is the render state information which is gathered, among others, from the Material.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Last edited by Spintz on Mon Dec 10, 2007 2:04 pm, edited 1 time in total.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

Spintz wrote:Also, this talk of the node maintaining the VertexBuffer and mesh data seems completely backwards to me.
Do you mean an AnimatedMeshSceneNode should request buffers to be created inside the AnimatedMesh, get an ID from it, then tell the AnimatedMesh to reskin and return the internal mesh with that ID?

I think what hybrid means is that, for example, we could have driver specific index lists via driver::createIndexList, and in the case of many animated mesh nodes, the index lists for each buffer are shared between the loaded buffer and the ones belonging to each node. (edit: edit: edit: trying to word it so it makes sense)

In that case, I suppose shallow copies of MeshBuffers could be made as a matter of practice, the materials could be different for each one (and get rid of meshnode::ReadOnlyMaterials), which makes sense.
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Post Reply