This is a way of creating volumetric fog in Roblox using beams. This simple yet effective system simulates light being influenced by fog, bringing a touch of realism and atmosphere to your game.
How?
The system uses beams positioned in front of the camera to simulate light scattering caused by fog… These beams adjust dynamically based on the camera’s field of view and resolution size. This setup is lightweight and customizable.
-- Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
-- Constants
local SETTINGS = {
LIGHT = {
PART_NAME = "LightRaySource",
EMISSION = 1,
INFLUENCE = 1,
COLOR = Color3.fromRGB(255, 255, 255),
CAMERA_OFFSET = 2
},
RAYS = {
COUNT = 100,
SPACING = 0.7,
TRANSPARENCY = {
MIN = 0.9855,
MAX = 1
}
}
}
-- Variables
local Camera = workspace.CurrentCamera
local raySourcePart = nil
local lightBeams = {}
-- Helper Functions
local function createPart()
local part = Instance.new("Part")
part.Name = SETTINGS.LIGHT.PART_NAME
part.Size = Vector3.new(1, 1, 1)
part.Anchored = true
part.CanCollide = false
part.Transparency = 1
part.Parent = Camera
return part
end
local function calculateBeamProperties()
local viewportSize = Camera.ViewportSize
local halfFOV = math.rad(Camera.FieldOfView / 2)
local beamWidth = (math.tan(halfFOV) * 2 * viewportSize.X / viewportSize.Y) * 150
return beamWidth
end
local function createBeamAttachments(parent, index, beamWidth)
local zOffset = -index * SETTINGS.RAYS.SPACING - (index == 0 and SETTINGS.LIGHT.CAMERA_OFFSET or 0)
local topAttachment = Instance.new("Attachment")
local bottomAttachment = Instance.new("Attachment")
topAttachment.CFrame = CFrame.new(0, beamWidth / 2, zOffset)
bottomAttachment.CFrame = CFrame.new(0, -beamWidth / 2, zOffset)
topAttachment.Parent = parent
bottomAttachment.Parent = parent
return {
top = topAttachment,
bottom = bottomAttachment
}
end
local function createBeam(parent, index, attachments, beamWidth)
local transparency = SETTINGS.RAYS.TRANSPARENCY.MIN +
(index / (SETTINGS.RAYS.COUNT - 1)) *
(SETTINGS.RAYS.TRANSPARENCY.MAX - SETTINGS.RAYS.TRANSPARENCY.MIN)
local beam = Instance.new("Beam")
beam.LightEmission = SETTINGS.LIGHT.EMISSION
beam.LightInfluence = SETTINGS.LIGHT.INFLUENCE
beam.Color = ColorSequence.new(SETTINGS.LIGHT.COLOR)
beam.FaceCamera = true
beam.Transparency = NumberSequence.new(transparency)
beam.Width0 = beamWidth
beam.Width1 = beamWidth
beam.Attachment0 = attachments.top
beam.Attachment1 = attachments.bottom
beam.Parent = parent
return beam
end
-- Core Functions
local function initializeSystem()
if #lightBeams > 0 then return end
raySourcePart = raySourcePart or createPart()
local beamWidth = calculateBeamProperties()
for i = 0, SETTINGS.RAYS.COUNT - 1 do
local attachments = createBeamAttachments(raySourcePart, i, beamWidth)
local beam = createBeam(raySourcePart, i, attachments, beamWidth)
table.insert(lightBeams, beam)
end
end
local function updateSystem()
if not raySourcePart then return end
raySourcePart.CFrame = Camera.CFrame
local beamWidth = calculateBeamProperties()
for _, beam in ipairs(lightBeams) do
beam.Width0 = beamWidth
beam.Width1 = beamWidth
end
end
-- Initialize
initializeSystem()
RunService:BindToRenderStep(
"UpdateLightRays",
Enum.RenderPriority.Camera.Value,
updateSystem
)
Now, if you find anything you want to let me know about the script that is bad, I will change it or fix it. I am not a great scripter but I wanted to show my method for fog.
note
I have made a demo place for you to try here, Custom "Lighting Engine" Demo - Roblox , RBLX file aswell. One final thing is if you are interested in how I made probes to show light bouncing I have used this awsome tool. LampLight - Global Illumination For Roblox (New v1.2). One final note, this is great for dark scenes with light sources, limited light sources may ruin the scene.
FogGame.rbxl (88.4 KB)
License
This script is completely open-source and free to use in any project. Feel free to modify and improve it as needed. If you enhance the script or use it in a game, I’d love to see what you create! just dont sell it and lable it as yours, unless modified heavily heavily,