Custom Baked Lighting “Engine”

Intro

A new update has been created here! Baked Lighting "Engine" - Update 1

This is an entire lighting-rendering simulation that’s designed to replace Roblox’s or add onto it. The way lighting is rendered using this system is pretty simple, and similar to how engines like Source render their lighting, where every surface is divided into a grid. The color of each grid box in that grid is then calculated based on raycasting to light sources, and directional lighting.

The images showcased are completely rendered only using this lighting system. Meaning that on Roblox’s Lighting service, technology is set to voxel, global shadows are set to false, and all ambient values are set to a solid color. All lights included within a scene are also disabled, and rendered only using the baked lighting engine.

Lighting is only rendered once throughout the given scene and is not dynamic. This could be useful for people on lower-end hardware which have a considerable performance impact by Roblox’s real-time lighting and shadow options, such as future lighting. Baked Lighting still allows realistic shadows and diffuse lighting regardless of the user’s hardware.

Real-time lighting though is also possible using only this system. This is seen in the last gif posted at the end of this article.

Things You Should Know (Updated 4/10/22)
If some of these things don’t make sense, make sure to read the rest of the post.

  • This framework is designed for boxes, meaning all parts (regardless of whether they’re wedges, balls, cylinders, etc.) will be treated as six-sided boxes.
  • This system is designed for Point lights, meaning any other type of light will be treated as a point light when rendered.
  • If rendering becomes slow, consider:
    1.) Making the size of the part you’re rendering smaller. Rendering an entire baseplate for example isn’t a good idea, since its size is massive. On top of this, tons of intricate tiny parts can increase lag, as several more faces have to be accounted for.
    2.) Making “bounding boxes” with simplified parts to render lighting for instead of rendering every detailed part in your scene could help with lag.
    3.) Changing the render scale to something larger.
    4.) This one is kind of a last resort. You could change the iteration and yield times in the lightmap module on lines 46 ad 47. What these values do is explained in the script.

How Do I Use It?
The core module: Lightmap.lua (21.3 KB)
A demo place file: DemoLightmapsParallel (3).rbxl (38.6 KB)

After requiring the Lightmap module in any script, there are a few functions you can use to start rendering baked lighting.

You can render baked lighting for specific surfaces of an object using:

lightmap.renderSpecificSurfaces(mainScript, faces, object, lights, renderScale, renderType, globalShadowsEnabled) ```
  • mainScript is the current script that’s running. This should just be passed in as script.
  • faces is a table with the faces you want to render baked lighting for. You can choose from “Top”, “Bottom”, “Right”, “Left”, “Front”, and “Back”
  • object could either be a BasePart or an Instance with parts in it
    which the lighting will be baked for.
  • lights is a table with the local light sources that will be taken into account when baking lighting.
  • renderScale is a number that states the size of each grid box in studs.
  • renderType is a string that states what elements of the scene will be rendered. You can chose from “FullLightMap”, “Shadows+AllLights”, and “OnlyShadow”. I’ll explain these options in further detail later.
  • globalShadowsEnabled is a boolean that states whether directional lighting will be taken into account when baking lighting.

You can also render baked lighting for all surfaces of an object:

lightmap.renderAllSurfaces(mainScript, object, lights, renderScale, renderType, globalShadowsEnabled) 

Removing all baked lighting can be done with:

lightmap.removeAllLightmaps()

Some of these properties might be a bit difficult to understand without visuals, so I’ll show some examples in the next sections.

Render Scale
As described earlier, render scale states the size of each grid box in studs. By default, it’s set to 2 on line 16 of the Lightmap module.The higher the value, the lower the quality of the baked lighting will be and vice versa. Keep in mind that higher render scales will take a lot less processing power to render compared to lower render scales.

(All objects with baked lighting are highlighted in red)

Render Types
As also described earlier, Render Types state what elements of the scene will be rendered.

Final Notes
Hopefully, that’s all you need to get started. Here are some demos created using the framework! Have fun baking!

(Chessboard)


(Crossroads)

(Realtime Shadows)
2022-04-07-23-34-28 (2)

121 Likes

can you please make this as a rbxl file because i dont understand all of it.

1 Like

Isn’t this the same as the enumeration for lighting types? Specifically Future type.

All this does is give different shadow options.

1 Like

After peeking through the code a bit, this code is actually calculating it’s own lighting using raycasting and decals. (Props to the author - light transport simulations are hard!)

In other words, you do not have to rely on Roblox’s lighting system for lighting. This is useful if you have a static map, which won’t change at all. So you can have super detailed lighting without having to switch to a different lighting engine, with almost no performance problems.

I believe that the images above are using voxel lighting, so you can see what kind of lighting you can get with this even when using low-end lighting techniques.

Having different shadow options is very useful when making maps. Sometimes you don’t want global lighting getting in your way, but you still want shadows, while keeping the daytime lighting, etc.

3 Likes

I probably should have specified more what baked lighting is.

AverageNekoEnjoyer is right, this is an entire lighting- rendering simulation that’s designed to completely replace Roblox’s OR add onto It (which is why there are multiple render types.

The images above though are completely rendered only using this lighting system. Meaning that on Roblox’s Lighting service in studio, technology is set to voxel, global shadows are set to false, and all ambient values are set to a solid color.

Lighting is only rendered once throughout the given scene and is not dynamic. This could be useful for people on lower-end hardware which have a considerable performance impact by Roblox’s real-time lighting and shadow options, such as future lighting. Baked Lighting still allows realistic shadows and diffuse lighting regardless of the user’s hardware.

The smooth shadow effect is done using a texture on a decal. When scaled, it can either give the effect of higher resolution or lower resolution shadows. In some cases depending on your render scale, It can give the effect of ambient occlusion.

I also just updated the actual post to include this information.

4 Likes

Here you go!

DemoLightmaps.rbxl (38.7 KB)

If you need any additional help, feel free to message me. This system might be a bit confusing to use for those who aren’t super familiar with Roblox scripting.

1 Like

Wait so this is like a totally different light engine right? like Future but more performant?

Yes, 100%. You can either make it completely standalone or only render specific features, such as shadows.

5 Likes

Might i ask how does it works? I am too small brain to understand the code.

It’s pretty much raytracing, except rays are cast for points on the surface of a part instead of for each pixel on the screen.

So for each point on a surface of a part, a ray is shot toward the sun and/or any nearby light sources. If any objects intersect the ray, then that point on that surface is in shadow.
Calculations are also done to determine the color of that point based on nearby light sources (their range, color, and brightness), how that point is visible to the sun (what Roblox’s Lighting.Brightness does basically), and also ambient colors set in the module.

3 Likes

This is really cool! I’m currently making this work with putting image labels inside of surface guis instead of parts with decals, ill update you when It’s finished!

1 Like

Would you be willing to release the crossroads rbxl file to the public?

This is very nice, great job! But why would you want to use this over Roblox’s default lighting? Seems unnecessary to me.

1 Like

It’s designed for rendering lighting for maps that are completely static. This ends up being more performant on lower-end hardware than using future lighting for example, while still supporting realistic local light shadows and other features. Since lighting is only rendered once, this ends up being pretty performant and also means that lighting stays consistent for any graphics quality.

3 Likes

I attempted implementing surface guis at first, but I noticed that the processing time ended up skyrocketing compared to decals.

It’s always nice to see sometihng new pop up on the dev forum that isnt the usual. Pretty cool!

2 Likes

How to a render an entire map? Here I am just doing a baseplate with an extra part added to it, but it has the error exhausted allowed execution time
image
image

Tried increasing the render scale but that didnt fix either

That is due to it looping and doing too much stuff which cause it to exede the max time, YOu could either bake part buy part, Or, Modifies the sources to add a Wait() function or task.wait

Nice!
Two things that can be optimized though:

  1. There is no yielding which will cause script timeouts:
    Custom Baked Lighting “Engine” - #17 by intergravitation

  2. Since this uses workspace:Raycast I believe it could be optimized using the new parallel lua feature.

Its still performance intensive with many part, I suggest to use greedy mesh algorithm to combine parts
also why doesn’t my spot light cast good looking shadow, all my light basically does nothing