Featured post

3.1 Sneak peek : Light culling and Single pass lighting

As many of you knows, JME 3.0 only has a Forward rendering pipeline. One of the major drawbacks of such a pipeline is that it basically does one geometry rendering pass for each light in the scene. Typical complexity of a scene in JME is (number of objects x number of lights).

This leads to big performance issues when you have several lights in a scene, that many of you experienced. Even with a fairly low amount of objects, many lights can quickly be a killer.

Until now the ways to alleviate the issue were to bake lights in textures, partition the scene graph and  attach lights to sub nodes… or implement your own deferred rendering pipeline… (more on this later).

We wanted to offer better and easier solutions for users.

LIGHT CULLING

The first new feature is light culling. It’s based on the observation that rendering a light that is not in the camera frustum or rendering an object for a light that doesn’t affect it is a waste.

jME now has a way to sort that out. On each frame, each light is checked once against the camera frustum and not rendered when it’s outside. Also each geometry is checked against each light in the frustum and only renderer if the geometry is in the area of effect of the light.

lightCulling

Figure 1 : With light culling this scene issues only 3 draw calls

For example, in today’s jME, figure 1’s typical scene would yield 6 draw calls : 3 for the red sphere, and 3 for the blue (1 for each light in the scene L1,L2 and L3).

With light culling this results in 3 draw calls : 1 for the red sphere ( only affected by L3) and 2 for the blue sphere (once for L3 and once for L2).

Implementation

So how do we do it? The RenderManager now has a LightFilter, that is called every time we want to render a geometry. There is a default implementation set (DefaultLightFilter).

This Filter extract the lights list to render for this frame for a given geometry. Of course each type of light have different way of checking their intersection with the frustum or with a geometry.

If you want to disable light culling it’s safe to set this filter to null.

Results

Here is a scene featuring 18 geometries and 18 lights. The grey ground is one big geometry, each blue cube is a geometry and the strange guy in the middle is one geometry. There is a directional light, a blue spot light in the center, and a point light above each cube.

In the first view you can see the whole scene rendered without light culling, the second is a subpart of the scene without light culling.

Top : The whole scene with no light culling (1.310ms) Bottom : The whole scene with light culling (1.262 ms)

Top : The whole scene with no light culling (1.310ms)
Bottom : The whole scene with light culling (1.262 ms)

Top : A sub part of the  scene with no light culling (1.760ms) Bottom : A sub part of the scene with light culling (1.195 ms)

Top : A sub part of the scene with no light culling (1.760ms)
Bottom : A sub part of the scene with light culling (1.295 ms)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

As you can see the performance gain is not huge when the whole scene is in the frustum, even if the number of geometries drawn is cut in half. The reason is that the culling itself has a cost, because it iterates over every lights for each geometry, and perform a bound check.

The gain is more substantial when looking at a sub part of a scene, Culling out lights from the frustum definitely yield a performance boost.

The geometries in the scene are very simple here, and the speed boost might be higher with more complex geometries. Also with more spread out lights in a bigger scene the gain is definitely higher when looking at a sub part of the scene.

But… This doesn’t dispend you to partition your scene and only light sub part of the graph with each lights. The culling will be a lot faster.

Noteworthy

Shadows now also use light culling. This means that shadow maps won’t be calculated for lights that are outside of the frustum. This can give a huge performance boost.

SINGLE PASS

Light culling is nice, but it’s not an absolute revolution in our rendering pipeline. We still have to render an object once per lights. Let’s get rid of that.

The idea behind single pass is to send a list of light information to the shader and to compute all the lights contribution while rendering the geometry once.

It’s been a long time that our material system had a way to select multipass or singlepass lighting. But the lighting shader was never implemented to support it. Now it’s done for Lighting.j3md and for TerrainLighting.j3md

You can set the preferred light mode on the renderManager. If you set it to SinglePass, the material will preferably select a technique that supports it.

In practice, you cannot just send ALL lights of the scene to the shader. Light data is sent as a uniform array and you have a limit in size that depends on the hardware. To alleviate this issue we decided to do one pass for a batch of lights. The size of the batch is configurable, and has a big impact on performances. I’ll explain how to find the right value in an more detailed documentation on the wiki.

Result

It the same scene as above, I’ve used single pass with a batch size of 6.

SinglePass

Top : Whole scene with single pass lighting (0.775 ms)
Bottom : Sub part of the scene (1.050 ms)

Compared to what you have in v3.0 (MutiPass lighting, with no light culling) rendering this scene  in SinglePass with light culling is overall 70% faster.

Pro and cons

There are not a lot of cons to be honest, but single pass require that the lighting calculation occurs in the fragment shader. This means that if you have only one light in your scene, Multipass lighting will be faster. But, computing lighting in the frag shader yields a more precise lighting, so even with a single light, you may have a render quality increased… you decide ;)

How does it perform compared to Deferred lighting?

I honestly don’t have a clue. But that can be a nice alternative if you have a moderate amount of lights, and avoiding all the querks you’ll hit with deferred rendering (difficulties for AA, transparency, material versatility, big memory bandwidth, etc…)

 

GSoC concluded and lessons learned

Our first GSoC and jMESoC adventure has come to an end. All 3 GSoC projects were successfully completed, while jMESoC got 2/4 (the other 2 never really started). Some of the students will be moving on to other projects, while others, to our great delight, have become active members of the community.

See the forum discussion thread for links to the projects.

What we’ve learned

There’s bound to be some mistakes as an administrator or mentor of GSoC the first time around. Well aware of this, we went into our first GSoC knowing full well that all we might get out of it was some cool proofs of concept and maybe a new contributor or two, along with newfound experience. It’s safe to say that this GSoC 2014 has delivered on all accounts, and then some.

Now about that newfound experience…

Students need more structure

We’re very used to working independently, and thrive as such. Students, while definitely very capable, benefit from more structure when being catapulted into a large beast like jMonkeyEngine. Mentoring sessions and weekly status reports should have been more rigorously scheduled.

The GSoC admin should be every bit as involved as the mentors

I never intended to be a as uninvolved as I was. Had I been more in the loop – doing frequent check-ins with both the mentors as well as the students – I believe we could have avoided several hiccups caused by miscommunications and lack of structure. Also some early exposure to seagull management is good for your skin.

Make sure jME plays an integral part

Some of these projects were so loosely attached to jME that a lot of the mentoring didn’t require expertise in jME at all, only Java or programming in general. Mentoring is both more fun and efficient when the project closely ties in with jME concepts at every turn.

Standardised development environments

Too much time was spent “on the clock” simply getting set up and getting to grips with key concepts like Git and SDK development. We should have formalised a proper Getting Started guide shortly after our GSoC participation was confirmed.

Grow from within and don’t start from scratch

This time around we accepted applicants based on application merit above all else. We don’t regret this decision, as we clearly picked 3 very capable students. However, by not factoring in previous experience and interest in jMonkeyEngine we made things more difficult for our students. All of the hiccups we did run into would have been greatly mitigated in the case of an existing contributor, especially when tasked with adding to a project that’s already active.

Will we apply for GSoC again next year?

Frankly, we don’t know yet. Make no mistake, GSoC is a big time investment, and if you’re out to get “free improvements” for your project, you’re probably barking up the wrong tree. To me, the single biggest win any project can come away with from GSoC is more committed contributors, so we recommend trying to grow from within.

Conclusion

GSoC is an excellent opportunity to recognise existing members of your community; developers who were already kicking your tires for no incentive other than “because they felt like it”.

We already considered prior jME knowledge when selecting students this year. If we try for GSoC again and get accepted, we will probably take this one step further. Students who have already been an active part of our community prior to GSoC or who are willing to step up and contribute to the community during the application process will be prioritised.

The projects we choose will be tied more closely into jME itself and we will make sure from the start that the work students are doing is integrated into the project as a whole. Publishing progress needs to be something that happens continuously and ideally early versions should be in use by members of the community as soon as possible to provide prompt feedback and help ensure that the end result is as useful and as well integrated as possible.

A heartfelt thanks to all our hardworking (G)SoC students! May the open source spirit grow ever stronger in your caffeine-empowered hearts!

Image1

Blendswap Arcade – At long last, we have a final verdict!

4 odd months later, and the Blendswap Arcade is concluded. To give me a deserved beating for my absence, please refer to my apology. In the end, Rickard @rickard swooped in as the 2nd judge together with Nicholas @memonick, and we had ourselves a final verdict. Which is…

1st Place – Hostage

Image1

Judge 1:
An ideal contest submission – doesn’t do a lot, but it is is polished and, most importantly, enjoyable. Contains some interesting mechanics and props which really spice the game up.

Judge 2:
Simple and surprisingly addictive. Could have benefited from another fail state, too many misses, to make it more difficult. Suggestions: Drop the voice on hit miss, replace with a sound effect. Have the hostage/civilian switch places.

2nd Place – Exterminator

exterminator

Judge 1:
Interesting game which could be extremely enjoyable on a smartphone or tablet. The game is rather challenging and frustrating, yet it could have used some more polishing when in the graphics.

Judge 2:
Simple concept, well executed. Well defined game states and boundaries. As frustrating as ‘whack-a-mole’ (in a good way).

3rd Place – Marbleway

marbleway

Judge 1:
Fun, challenging and tedious, Marbleway makes perfect use of the theme and is solid all around. The only areas it lacked in are the camera movement and the physics, which sees undesired consequences, such as the marble getting caught beneath seats.

Judge 2:
Classic gameplay. Camera somewhat annoying. The game would benefit more from open levels (no walls in the way for camera).

All of the games made for the contest are freely available here:

http://hub.jmonkeyengine.org/wiki/doku.php/jme3:blendswaparcade

Epilogue

The Blendswap Arcade contest definitely had its share of flaws in both planning and execution, which I take full responsibility for. But in concept, I think it works exceedingly well (yeah I know that’s also what they say about communism, but this is different, read on).

The games speak for themselves. There were some concerns that 10 games using the same asset could easily result in 10 near identical game experiences, but in retrospect this concern was unwarranted. Game design muscles were amply flexed that week. Indies, I applaud you.

If someone else from the community ever wants to do another contest, re-using this concept or doing something new, please get in touch; I’m not gonna be in the driver’s seat, but I can help.

If I’m not mistaken, Rickard is eager to do a contest of his own to celebrate the release of his kick-ass “jMonkeyEngine 3.0 Cookbook”. Keep an eye out!

Comment on this thread