Minecraft-like Voxel type lighting?

How do I detect these parts & change the imageColor (or a better way) to be darker / lighter depending on the distance of the first part? And what if there are two parts next to eachother?

Heres an example:

The blocks around the torch are lighter.
The parts exposed to light are normal, while the ones further are darker.


3 Likes

This video covers a number of things, and some of it is a bit outdated as it only applies to classic or older versions of Minecraft, but the lighting section is still relevant:

Current Minecraft is only different in that those values are interpolated rather than only changing per voxel surface.

2 Likes

Thanks. But how would I detect this in Roblox? If I used raycasting would it be laggy?

1 Like

And how would I check all the blocks around the torch, and make the ones around those ones have a bit of a lower light level?

2 Likes

Is your game actually voxel based? If so, every voxel would have a light value. You can assume that every surface voxel has a light level of 15 (during the day). If voxels are ever placed above a surface block, whether from the next generation stage or through player action, you can have the light level adjust at that point. When a light source block is placed, that’s when you would get all nearby voxels and adjust their light level based on their voxel distance from the light source. You wouldn’t use raycasts or any sort of physical detection, you would just use an array of voxel data (likely chunk data if you’re going the Minecraft route). Though I should clarify that the light level stored is actually based on light sources, the light level from the sun is only one value for all surface blocks that aren’t obstructed.

If your game isn’t actually voxel based or at least isn’t procedurally generated, then I suppose raycasts could work as a simple way to generate this visual.

4 Likes

Yeah, my game is voxel based. But what do you mean by using an array of voxel data?

2 Likes

I was maybe thinking detecting the parts on the sides of each part, and checking the light level of it, then if the light level of it is 15. I’d make the part light level 14. Etc. Idk if that’d be laggy tho

2 Likes

And that wouldn’t be great if it’s daylight because all the blocks would be light level 15.

1 Like

If you’re using a chunk system like Minecraft, a chunk size should be x=16,y=256,z=16. The reason for this is storage. One byte, made of 8 bits, can have up to 256 combinations, and can therefore store either a value of 0 to 255 or 1 to 256. This means that the Y axis can be stored with a single byte. Now the amount of possible combinations is calculated by 2^bits, and 2^4 (4 bits is half a byte) is 16, which means the X and Z axis can be stored with a single shared byte. So a chunk could have a 3D array for every voxel in that chunk with the required data.

Though do note that for the purposes of data saving, you’ll need more than 2 bytes as that only gives you the voxel’s position. Also these positions are offset positions, which are all relative to the chunk’s position (it’s cheaper to save 2 bytes worth of data for a position rather than the full world position, which only the chunk needs to know).

1 Like

Not sure if this could help but you could try doing something like this:

if your game is with blocks, then find the position where the torch is placed, then, the block which has the torch on top will have the highest light color, and each block further will slowly make it darker and darker until it matches the night darkness

1 Like

It’s better to use an array of data as it’s very cheap to look up voxel data that way. The overall lighting calculations are also very quick and only need to occur when a light source has either been placed or removed. You could technically use other methods like you’ve mentioned, but I wouldn’t recommend it as it’s far less performant. Though due to these calculations being infrequent, it’s not as though it’s a terrible option. Though surface light level is calculated differently.

How would I do it using arrays? I haven’t really used arrays much.

I would highly recommend learning arrays as they’re extremely useful in a lot of ways.

You’ll use a 3D array that will appear as chunk[x][y][z] to get the particular voxel data. You’ll also be able to iterate over the array for each axis. I’d recommend writing a function to get all nearby voxels within a given distance, but it’ll need to support gathering voxel data from neighboring chunks. If you’re not using chunks, which is fine if you’re not going to save any data, then you can just have one big 3D array for everything, however then you’ll definitely need to write a function to get nearby voxels as iterating over an entire world worth of voxels will obviously take a bit of a performance hit.

Hopefully this helps you:

Okay, I’ll try this out and let you know how it goes.

I read the documentation, but how would I detect the light source of each block in the chunk and then change the light source of the surrounding ones depending on that?

Alternatively, if you’re not using chunks or saving data, a less performant but easier method would be to get all parts within a range using something like GetPartBoundsInRadius, and then applying light level that way, though you may want to do something to see if that part is even possible to be lit by the light source from wherever it is. Definitely don’t light up, or even generate, blocks that aren’t touching air as that would be wasteful.

Light level is one of the things that will be stored with each voxel. Next to their position, half a byte can be used to store the light level of 0 to 15. Though if not using an array, you can just use attributes to store a light level.

I am using chunks.

char limit sadkjhk

I’ll probably go with attributes. How would I go about changing the light level of the blocks around it though?

You’d just get the nearby blocks and set their light level to something relative to the distance from the light source. Just note that if there is more than one light source, you’d store the highest value between them for that voxel’s position. The light value from the sun doesn’t need to be saved as that’s a global value. A surface block with no obstruction will always have a light level of 15 during the day and therefore doesn’t need to be stored or calculated, it will always be the highest value until it’s not. Now if this is for purely visual stuff, I’d only worry about light sources as it would be incredibly inefficient to change the light level of every surface block whenever the day/night cycle shifts a stage. This sort of thing is normally done on the GPU rather than the CPU.