RTX V1
Key RequiredUniversal

RTX V1

Universal Scriptc00lkiddscriptsc00lkiddscripts 25.1K views 107 executesUpdated Aug 2, 2025
2.5/ 5(2 votes)
1150% Positive
Lua Script•208 lines (6981 chars)
-- Services so it can take control of the lighting engine 
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Lighting = game:GetService("Lighting")
local Workspace = game:GetService("Workspace")
-- Disable built-in lighting effects modify this to lighting brightness 0 but it will be very dark unless you crank up all the ray numbers lol
Lighting.Brightness = 0.2
Lighting.Ambient = Color3.new(0, 0, 0)
Lighting.OutdoorAmbient = Color3.new(0, 0, 0)
Lighting.GlobalShadows = false
Lighting.EnvironmentDiffuseScale = 0
Lighting.EnvironmentSpecularScale = 0
local localPlayer = Players.LocalPlayer
local camera = Workspace.CurrentCamera
-- Wait for the player's character to load
local character = localPlayer.Character or localPlayer.CharacterAdded:Wait()
-- settings
local sunDirection = Vector3.new(1, -1, 1).Unit -- Adjusted sun direction
local sunColor = Color3.fromRGB(255, 255, 224) -- Soft sunlight color
local sunIntensity = 100 -- Sun intensity
local skyColor = Color3.fromRGB(135, 206, 235) -- Sky blue color
local skyIntensity = 0.5 -- Sky intensity
local maxDistance = 50000 -- Maximum distance for rays
local gammaCorrection = 10 -- For gamma correction
-- LOD Settings
local maxRays = 100000 -- Maximum number of rays per point
local minRays = 10000 -- Minimum number of rays per point
local lodDistance = 200 -- Distance at which LOD reduces rays
local function getSurfaceNormal(part, position)
	if part:IsA("MeshPart") or part:IsA("UnionOperation") then
		-- Approximate normal for MeshParts and Unions
		local normal = (position - part.Position).Unit
		return normal
	else
		
		local relativePosition = part.CFrame:PointToObjectSpace(position)
		local halfSize = part.Size / 2
		local normals = {
			Vector3.new(1, 0, 0),
			Vector3.new(-1, 0, 0),
			Vector3.new(0, 1, 0),
			Vector3.new(0, -1, 0),
			Vector3.new(0, 0, 1),
			Vector3.new(0, 0, -1),
		}
		local distances = {
			math.abs(halfSize.X - relativePosition.X),
			math.abs(-halfSize.X - relativePosition.X),
			math.abs(halfSize.Y - relativePosition.Y),
			math.abs(-halfSize.Y - relativePosition.Y),
			math.abs(halfSize.Z - relativePosition.Z),
			math.abs(-halfSize.Z - relativePosition.Z),
		}
		local minDistance = math.huge
		local normal = Vector3.new(0, 1, 0)
		for i = 1, 6 do
			if distances[i] < minDistance then
				minDistance = distances[i]
				normal = normals[i]
			end
		end
		return part.CFrame:VectorToWorldSpace(normal)
	end
end
local function computeLightingForPoint(part, position)
	local accumulatedColor = Color3.new(0, 0, 0)
	local surfaceNormal = getSurfaceNormal(part, position)
	
	local offsetPosition = position + surfaceNormal * 0.01
	
	local distanceFromCamera = (camera.CFrame.Position - position).Magnitude
	local numRays = maxRays
	if distanceFromCamera > lodDistance then
		numRays = math.max(minRays, math.floor(maxRays * (lodDistance / distanceFromCamera)))
	end
	-- Accumulate light from sky
	local skySamples = 10000000
	local skyLight = Color3.new(0, 0, 0)
	for i = 1, numRays do
		
		local u = math.random()
		local v = math.random()
		local theta = math.acos(math.sqrt(1 - u))
		local phi = 2 * math.pi * v
		local x = math.sin(theta) * math.cos(phi)
		local y = math.cos(theta)
		local z = math.sin(theta) * math.sin(phi)
		local randomDirection = Vector3.new(x, y, z)
		randomDirection = randomDirection.Unit
		
		local up = Vector3.new(0, 1, 0)
		local rotation = CFrame.fromAxisAngle(up:Cross(surfaceNormal), math.acos(up:Dot(surfaceNormal)))
		randomDirection = rotation:VectorToWorldSpace(randomDirection)
		
		local rayParams = RaycastParams.new()
		rayParams.FilterDescendantsInstances = {part, character}
		rayParams.FilterType = Enum.RaycastFilterType.Blacklist
		rayParams.IgnoreWater = true
		local result = Workspace:Raycast(offsetPosition, randomDirection * maxDistance, rayParams)
		if not result then
			-- Reaches the sky
			skyLight += skyColor
			skySamples = skySamples + 1
		end
	end
	if skySamples > 0 then
		skyLight = (skyLight / skySamples) * skyIntensity
		accumulatedColor += skyLight
	end
	
	local normalDotLight = math.max(0, surfaceNormal:Dot(-sunDirection))
	
	local rayParams = RaycastParams.new()
	rayParams.FilterDescendantsInstances = {part, character}
	rayParams.FilterType = Enum.RaycastFilterType.Blacklist
	rayParams.IgnoreWater = true
	local sunOccluded = Workspace:Raycast(offsetPosition, -sunDirection * maxDistance, rayParams)
	local shadowFactor = 1
	if sunOccluded then
		shadowFactor = 0 -- In shadow
	end
	
	local materialReflectance = part.Reflectance
	local materialColor = part.Color
	
	local sunIntensityFactor = normalDotLight * sunIntensity * (1 - materialReflectance) * shadowFactor
	local sunLight = sunColor * sunIntensityFactor
	
	sunLight = Color3.new(
		sunLight.R * materialColor.R,
		sunLight.G * materialColor.G,
		sunLight.B * materialColor.B
	)
	accumulatedColor += sunLight
	
	accumulatedColor = Color3.new(
		accumulatedColor.R ^ (1 / gammaCorrection),
		accumulatedColor.G ^ (1 / gammaCorrection),
		accumulatedColor.B ^ (1 / gammaCorrection)
	)
	
	accumulatedColor = Color3.new(
		math.clamp(accumulatedColor.R, 0, 1),
		math.clamp(accumulatedColor.G, 0, 1),
		math.clamp(accumulatedColor.B, 0, 1)
	)
	return accumulatedColor
end
local parts = {}
-- Gather all relevant parts once
local function gatherParts()
	parts = {}
	for _, obj in pairs(Workspace:GetDescendants()) do
		if obj:IsA("BasePart") and obj.Transparency < 1 then
			-- Set material to SmoothPlastic for consistency (optional)
			obj.Material = Enum.Material.SmoothPlastic
			table.insert(parts, obj)
			-- Ensure parts do not cast default shadows
			obj.CastShadow = false
		end
	end
end
gatherParts()
local function updateLighting()
	for _, part in ipairs(parts) do
		-- Compute lighting for the part's position
		local partPosition = part.Position
		local color = computeLightingForPoint(part, partPosition)
		if color then
			part.Color = color
		end
	end
end
RunService.RenderStepped:Connect(function()
	updateLighting()
end)
Workspace.DescendantAdded:Connect(function(descendant)
	if descendant:IsA("BasePart") and descendant.Transparency < 1 then
		descendant.Material = Enum.Material.SmoothPlastic -- Optional
		table.insert(parts, descendant)
		descendant.CastShadow = false
	end
end)
Workspace.DescendantRemoving:Connect(function(descendant)
	if descendant:IsA("BasePart") then
		for i, part in ipairs(parts) do
			if part == descendant then
				table.remove(parts, i)
				break
			end
		end
	end
end)
-- Include player's character in the raycasting
local function addCharacterParts(character)
	for _, part in pairs(character:GetDescendants()) do
		if part:IsA("BasePart") and part.Transparency < 1 then
			table.insert(parts, part)
			part.CastShadow = false
		end
	end
end
addCharacterParts(character)
-- Update character parts when character respawns
localPlayer.CharacterAdded:Connect(function(newCharacter)
	character = newCharacter
	addCharacterParts(character)
end)

Features & Information

shaders

Community Comments (0)

No comments yet for this script.

More Scripts for Universal Scripts