(March 2017) Monthly WIP screenshot thread

:open_mouth: i want that tool too!

I decided it’s time to implement clustered shading since that seems to be the best solution for handling lights currently, especially because it works with deferred and forward rendering. (You can also mix and match, like deferred for opaque geometry and forward for transparent stuff.)
Also it decouples geometry size from lights affecting it (a bit of a problem with the single pass lighting approach)

Essentially you build a three dimsional grid, test for each cluster in the grid which lights are close enough, with this information you save the amount off lights and an offset for each cluster. With that offset+number of lights you can then look into a second array which contains a list of indices to the actual lights which are stored in a third array. Then you can just loop over all those lights and do your lighting.

// get the index for the grid array.
int index = calcClusterOffset(gl_FragCoord.xy, linearDepth);
// look up offset and number of lights in the current cluster.
ivec2 lightIndexOffsetAndCount = grid[index].indicesPoint.xy;
for (int i = 0; i < lightIndexOffsetAndCount.y; i++){
    // look up the index for the light from the index array.
    int pLightIndex = pointLightIndex[lightIndexOffsetAndCount.x+i];
    // pick the light and do your lighting calculations with it.
    gl_FragColor.xyz += doLighting(pointLight[pLightIndex]);
}

The whole thing needs uniform buffer objects, so i had to add those to the engine (I don’t really know what I’m doing there and arrived at a working version through trial and error).

For now I’ll keep improving this as the need in my game arises, but i’m open to publishing the source/integrating it into the engine if there is interest.

512 lights, right side visualizes how many lights affect each cluster (white would be 40+, though there is no white ;)).

13 Likes

Nice, I need to learn it someday.

Maybe the light implementation is a little bit game specific, but uniform buffer objects is definitely a core engine feature.

I hope that you and the core team want to integrate this in the engine.

ha cool! Very nice !
Note that UBO are only opengl3.1 so if you add them to the engine maybe you need a fallback for opengl <3.1…
THe nice part with UBO is that you can share them between shaders. For lights it totally makes sense. Though you have to be careful to not update them on each frame.

One buffer for the gpu, one buffer for the driver and one for the cpu. :wink:
At least my experiments show no more gain if quadbuffering is used

Not sure what quad buffering has to do with UBO. Usually the gain is that when you have 10 uniforms in an UBO you only have one call to send them to the shader instead of 10.

If you update the same gpu buffer every frame it causes stalls. At least for memory mapped buffers you need “tripple buffering” to get away without waits

ha yes, that’s why I said you have to avoid to update them on every frame.
It’s not a silver bullet, but it can help in some cases.

yah. was not ment as opposing agrument to your comment. More like an addon. If you use 3 buffers and swap them it’s usually faster.

Not sure why 3 is the magic number, but it works better then 2 and same as 4 :smile:

1 Like

I’m currently updating every frame, all the lights are moving, the buffer for all lights with a fixed number of 1024 lights is only 32kB i don’t think that will cause stalls.
Also my indices list pointing into the light buffer is 256kB big + 32kB for the grid, though those could probably be stored as shorts or something to cut them in half and the indices list size is just set very large so that i won’t run into problems there.
Though i didn’t try any swapping yet, but optimizing performance if rendering the whole thing (with a worst case scenario) takes like 2 ms is a bit premature anyway.

1 Like

Glad it works for you. Tiled lighting combined with a deferred lighting is imho the best you can do nowadays

Heheh… if I finish the export to j3o option then maybe I will post it somewhere.

I like the vegetation.

1 Like

I can now load files too! Hehe. I added saving before and can visually inspect the files to see if they are right… but I couldn’t load them yet. I just added that.

So I was able to load my castle and tweak it a bit… I went with more of a stylized “cartoon” scaling which gives it a bit more personality and will probably ‘read’ better in a far away view.

5 Likes

so what the url for this project checkout? :smiley:

I would very much like your additions to the engine seen in core. Especially the uniform buffers are a feature that should be in core, but also the tiled lighting implementation is quite interesting, depending on how independent it works from your game specific use cases, it might make a good core addition, or at least a very good custom lighting shader example

Alright I’ll clean the uniform buffer code up so that it can be reviewed.
And i will keep working on the clustered lighting and publish it once it is usable, things i want to add currently are (It’s more of a wishlist):

3 Likes

I believe this person has a working skin shader in one of the plugins:

Though its for Panda3d, I think it might translate over.

Thanks looks like he uses this: Real-Time Realistic Skin Translucency, It would translate without any problems i think, but i’ll take a look at few more presentations/papers from siggraph and gdc first.