There are technics to work with many lights ,like using a deferred renderer and ligth volumes. See “A large number of lights” in LearnOpenGL - Deferred Shading.
Babylon already has global illumination: Babylon.js docs
Yes, sorry I thought he is looking for deferred rendering AND global illumination.
lighting is always a headache in babylon, would be awesome to have an ability to render more lights.
I can’t believe how much you achieved there within so few lines of code. Mind blowingly impressive Hoping this will get merged into core
Would that cause an extra draw call per mesh/material? If yes, may I ask whether this could be toggleable (is that a word)? Because in the current state it is already super useful for cheap (as in 1 draw call) lights scattered around the game world.
@Heaust-ops I went to a battle test and implemented the code in my local project. I have to say that I tested on a low spec machine. You know the more gamers I can reach the better. But even for 5 lights, frames dropped by over 50%.
I played around with the code and there is something I do not understand. I am using a slightly adapted playground: https://playground.babylonjs.com/#M6W2LC#21
Line 249:
//60 fps
vec3 justCallingIt = getColor(
abs(ci.a * 10.0),
vec3(true_px, true_py, true_pz),
normalize(ci.rgb),
color,
normals,
pbuff,
refl
);
//60 fps
//just adding to it
//color.rgb += color.rgb;
//color.rgb += color.rgb;
//color.rgb += color.rgb;
//60 fps
//color.r = justCallingIt.r;
//frame drop 50%!
//color.r += justCallingIt.r;
/*
//frame drop 50%!
color.rgb += getColor(
abs(ci.a * 10.0),
vec3(true_px, true_py, true_pz),
normalize(ci.rgb),
color,
normals,
pbuff,
refl
);
*/
Why do frames drop when I plus to color.rgb. I can assign, I can call. But plus-ing kills it?
Did some testing:
- Base w/o DeferredLights: 60fps
- 1 light: 50fps (+/- 5)
- 25 lights: 40fps (+/- 1)
- 55 lights: 20fps (+/- 1)
TOTAL_POINT_LIGHTS_ALLOWED
: Decreasing it has no effect. Increasing it (e.g. 16*1024) only increases loading time but not fps.
Oh! I did not consider that. Might just be a hardware limit in the end. So I don’t want to waste too much of your time.
Aww man I wish I could help you. But my GPU coding skills are on hello-world-level. Up until the lights loop I can kind of follow but then it gets tough.
But in the meantime first actual results: Lights out and on in Demo Town
I takes a bit of tinkering getting distance/intensity right but it is so worth it.I do not have light emitting level objects yet. So I just placed some random lights.
Oooh, it seems like fps got a 50% boots @ 55lights on my low spec machine All hail the shader god @Heaust-ops
I did some reading over the weekend (and learned a lot; also thanks to your code!).
In an earlier version you used e.setFloatArray3("lights_position", posArr)
instead of e.setTexture("lights_color_intensity_position", pointLightsDataTexture)
. I have got to say the array-version runs even faster (@55 lights) than the latest performance improved version using textures.
Did you switch because of the array max size limit? If so, maybe there could be two modes:
- Performance mode, uses array uniform but limits lights to MAX
- Flex mode, uses texture lookup supports millions of lights but may be slower
This way you could dodge the complicated velocity thingy.
Nice
Found some minor issues.
- When performance mode is on, colors need to be in 0-1 range whereas when perfomance off colors in 0-255. LL 145, 315, 319
- Setting DeferredLighting.isPerformanceMode to true was silently reverted by enable() by default parameter. LL 65, 184
(https://playground.babylonjs.com/#M6W2LC#31)
But then something weird again. I spent like the last hour debugging performance issues where, even with performance mode on, I would not go over 30fps Compare this to the base at reference https://playground.babylonjs.com/#M6W2LC#29 (Chrome; important to not drag the split screen; Inspector closed; 1K cubes (not spheres), 55 lights). When loaded up, not touching the mouse, I am getting 60fps
Anyway, I loaded up the 30fps playground one last time to double check something for this post, and suddenly I am at 50fps? wtf?? I have opened and closed Chrome now serveral times. Stays at 50. So I guess that is a win now
@Heaust-ops I think I might have found a performance improvement. The gbuffer doubles draw calls (like the glow layer). The prepass renderer does not seem to do that - but has all the textures the gbuffer has. I am not sure if there are any other side effects when replacing the gbuffer with the prepass renderer. But it looks like it is working:
Amazing! Now I want this to be added to babylon.js very much!
We can control the light color and intensity for each light in the building (the blue bars) but so far I had no options to illuminate the rooms by the light’s color. Regular lights can not be used because there are a lot of them. And this is just a small demo building.
Your stuff could make it happen! Thanks so much!
Go go go @Heaust-ops !!!
Aaand +1 big point for using Typescript
And you deserve an award for this one:
EDIT:
and let me continue to flatter the PG is nicely formatted, well written… Everything is so perfect! Congrats dude! KUDOS!!
Yeah sorry @Joe_Kerr not to mention you! You deserve all the compliments and kudos as well!!
I believe we could ask @Evgeni_Popov to review the code/shader to push the maximum juice out of it!
Huge playground peformance boost on my toaster! Great job @Heaust-ops!
Need to get a workflow going from placing lights → render in Babylon. Will report back with some night ops mission screenshots.
@Heaust-ops sorry for bothering you. May I ask if you could have a look at this playground: https://playground.babylonjs.com/#M6W2LC#39
I thought the cubes should be equally lighted where they touch the sphere. But this only happens at low camera angles (cam forward parallel to the ground).
Is this right?
Nice, thanks