Hey folks,

Multipass is ready for review. The basic gist is that I’ve removed the single array of RenderStates in Spatial and Geometry (not current and default arrays though as those are not directly related) and in their place I’ve added ArrayLists of StateList objects. The StateList object is a simple class holding a single array of RenderStates.

The system will draw a given Geometry X times, where X is the number of StateList items in that Geometry’s states ArrayList. Each time through, it will use the next StateList’s renderstates to do the draw.

The trick to this code was not in getting things to draw more than once, but to integrate this with our state collapsing system, our various optimization techniques and so forth. So far I have not seen a significant hit in FPS in running tests before and after the change. ymmv.

You don’t actually need to know any of this to use Multipass though. Simply add an index param when you call setRenderState and it will assign the indicated state to that index’s statelist. (indexes are drawn 0, 1, 2… X)

I’ve included a test to show multipass in action. Basically it recreates multitexturing the old fashioned way (rendering the object twice, once for each texture.)

Patch File (first time trying this… so hope it makes sense!)


PS: Sorry, you’ll notice the patch includes a few import cleanups I took care of along the way. ://

  1. Did you use my code or any part of it?
  2. How did you solve the problem of priorities? What I mean is that there are cases in witch, for example, you want to render the primary graphics then the stencil buffer for the entire sean then finally rendering the actual graphics that use the stencil buffer. In other cases the you want to have all the pass drone for each spatial before going on to the next.
  1. There’s not that many ways of doing this, so the approach you took is similar, but I ended up writing this from scratch. The reasons I did so… A. your code did not respect certain areas such as the rendering optimizations… B. It’s a small enough chunk of code, so any amount of extra work on my part was minimal. and finally (perhaps most importantly) C. by writing from scratch I had all of the code commited to memory so it was easier to keep the whole picture in my head.
  2. I haven’t taken care of a situation as you describe it using something like priority. I can certainly look to that. I was thinking of redraw on a Spatial by Spatial basis. A scene by scene approach is interesting. I don’t see how your code would handle multiple passes on a Spatial by Spatial basis though the way you handle it via the queue. So it looks like I need to find a way of merging the two methods.

    FYI: On a different note, renderstate collapsing occurs index by index… So if you add a lightstate to the rootnode in index 0, it will only affect and be combined on the 0 index of all it’s children (as you would expect.)


hehe, um… what the?

After considering this even further, I’m not sure exactly what techniques require grouping passes in large scenes. Can someone help me out here? Looking at 3d stencil buffer techniques, it seems like doing the stencil and then color passes back to back, spatial by spatial, should work ok for things like compositing or shadows.

Can this be comitted?

I was hoping to hear from Chman since he is the shadow expert. Wanted to make sure this will take care of his needs to getting shadow volumes, see if there is anything additional he needs, etc.

Making good shadow volumes (that can handle artifacts), You basicly need 3 passes :

  1. Draw the entire scene.
  2. Cast the shadows for wanted objects.
  3. Redraw the scene in shadowed areas with proper lighting and textures (else the shadows would be totally black).

    I haven’t look at your code renanse, but if it can handle Full scene multipass, shadows could be integrated :slight_smile:


Right, so my question is still what part of the shadows requires the pass be done on the full scene (full scene on each pass) rather than multiple passes per scene object? I’m sure it is required, but I want to understand in what way so that the code can be written most efficiently.

It depends of the way you implement shadows, but the most used way is to render the full scene first, then process shadows for each objects. That’s the way I would implement shadows into jME.


renanse, the code i gave you can handle rendering the entire scene before going on to the next step.

Badmi, the code you gave me could only do so if the entire scene was all transparent/opaque.

:// I cant believe I did not see that. It may work better if you put all the spatials in the same bucket and then used the compare method to separate them. What I originally planed to do is put the loop in the node that the Effect was originally attached to but that would not of worked with the render query. Maybe you should try having a different query for each pass that needs to have multiple spatials. If you want to force the user into rendering the entire sean each pass you then all you need to do is have a set Render State Pass function and call Renderer.draw multiple times. Good luck thinking of a solution.

Ok, here’s my thought. What about adding a MultipassNode class to my above solution that would apply a set of RenderStates and then render all of its children (without setting their states.) You could set X number of sets of renderStates on the node and it would make a pass for each. When it was done, it would then optionally render the children as normal (for your final texturing pass). You could also set into MultipassNode a blank set of renderstates which would signal to render the children with their own states for that pass in case you need textures and lighting to occur in a first/middle pass (or multiple passes) instead of at the end.

Multipass then becomes incompatible with renderqueue, it would essentially enforce SKIP mode (instant draw). This should be ok in most cases. Obviously we can go back and rework pieces that fail us.

Why not let MultipassNodes be added to the render query? Or you can use my method for the render query if and combine the transparent and opec buckets.

Yeah, read what I wrote again.

After discussing this with chman, the multipass node should fit his needs nicely. He’ll subclass it to make a shadow node. I’m hoping to have my part ready by tomorrow evening (tonight have the parents over.)

FYI. Going to hold off on this… The changes I’d like to put in place to handle it are a bit large and I’m not really foreseeing a lot of architecting going on so I’d rather not wedge something in at the present.

This is a high priority.