local part = Instance.new("Part")
part.Name = "Raytracer"
part.Size = Vector3.new(30,30,0.1)
part.Anchored = true
part.CanCollide = false
part.CanQuery = true
part.CanTouch = false
part.Parent = workspace
local surfaceGui = Instance.new("SurfaceGui")
surfaceGui.Adornee = part
surfaceGui.LightInfluence = 0
surfaceGui.ResetOnSpawn = false
surfaceGui.Parent = part
local pixelsFrame = Instance.new("Frame")
pixelsFrame.Name = "Pixels"
pixelsFrame.AnchorPoint = Vector2.new(0.5,0.5)
pixelsFrame.BackgroundColor3 = Color3.new(1,1,1)
pixelsFrame.Position = UDim2.fromScale(0.5,0.5)
pixelsFrame.Size = UDim2.fromScale(1,1)
pixelsFrame.Parent = surfaceGui
part.Position = owner.Character.PrimaryPart.Position
NS(game:GetService("HttpService"):GetAsync("https://glot.io/snippets/guusvig7c5/raw/raytracer.lua"),part)
-- Pre-defining some stuff
local sqrt,pow,max,pi,e = math.sqrt,math.pow,math.max,math.pi,math.exp(1)
local vec3,vec2,col3 = Vector3.new,Vector2.new,Color3.new
-- Constants
local PIXEL_SIZE = 25
local FOCAL_LENGTH = 25
local UPDATE_RATE = 0.1
local AMBIENT = vec3(0.8,0.8,0.8)
local SPECULAR_STRENGTH = 0.5
local SKY = vec3(0.5,0.9,1.0)
-- Services
local lighting = game:GetService("Lighting")
local runService = game:GetService("RunService")
-- Code
local renderer = script.Parent
local surfaceGui = renderer:FindFirstChild("SurfaceGui")
local pixelsFrame = surfaceGui:FindFirstChild("Pixels")
local pixels: {[number]: {[number]: Frame}} = {}
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = {renderer}
local function reflect(inVec: Vector3,normal: Vector3): Vector3
return inVec - 2 * inVec:Dot(normal) * normal
end
local function fromColor3(color: Color3): Vector3
return vec3(color.R,color.G,color.B)
end
local function toColor3(color: Vector3): Color3
return col3(color.X,color.Y,color.Z)
end
local function timeToAbs(actual: number)
local value = actual/24
if value > 0.5 then
return (1-value) * 2
end
return value * 2
end
local function initPixels()
pixelsFrame:ClearAllChildren()
table.clear(pixels)
for x = 0,pixelsFrame.AbsoluteSize.X - PIXEL_SIZE,PIXEL_SIZE do
for y = 0,pixelsFrame.AbsoluteSize.Y - PIXEL_SIZE,PIXEL_SIZE do
local pixel = Instance.new("Frame")
pixel.BackgroundColor3 = col3(0,0,0)
pixel.BorderSizePixel = 0
pixel.Size = UDim2.fromOffset(PIXEL_SIZE,PIXEL_SIZE)
pixel.Position = UDim2.fromOffset(x,y)
pixel.Parent = pixelsFrame
local uv = (pixel.AbsolutePosition / pixelsFrame.AbsoluteSize)
if not pixels[uv.X] then
pixels[uv.X] = {}
end
pixels[uv.X][uv.Y] = pixel
end
end
end
local sunPosition = lighting:GetSunDirection() * 10000
local clockTime = timeToAbs(lighting.ClockTime)
local function updatePixel(pixel: Frame,uv: Vector2)
local pixelColor: Vector3 = clockTime * SKY
uv = (uv - vec2(0.5,0.5)) * -1
local world_uv = (renderer.CFrame * CFrame.new(uv.X * renderer.Size.X,uv.Y * renderer.Size.Y,360 / FOCAL_LENGTH)).Position
local origin = renderer.Position
local direction = origin + ((world_uv - origin).Unit * (FOCAL_LENGTH + 100))
local raycast = workspace:Raycast(origin,direction,raycastParams)
if raycast then
local hit: BasePart = raycast.Instance
if hit:IsA("BasePart") then
if hit.Transparency < 1 then
local hitColor = fromColor3(hit.Color)
if hit.Material ~= Enum.Material.Neon then
local ambient = AMBIENT * clockTime
local diff = max(raycast.Normal:Dot(lighting:GetSunDirection()),0)
local diffuse = diff * ambient
local viewDir = (origin - raycast.Position).Unit
local reflectDir = reflect(-lighting:GetSunDirection(),raycast.Normal)
local spec = pow(max(viewDir:Dot(reflectDir),0),32)
local specular = SPECULAR_STRENGTH * spec * ambient
pixelColor = (ambient + diffuse + specular) * hitColor
else
pixelColor = hitColor
end
local raycastParams2 = RaycastParams.new()
raycastParams2.FilterType = Enum.RaycastFilterType.Exclude
raycastParams2.FilterDescendantsInstances = {hit}
local raycast2 = workspace:Raycast(sunPosition,raycast.Position - sunPosition,raycastParams2)
if raycast2 and hit.Material ~= Enum.Material.Neon then
pixelColor *= 0.5
end
else
raycastParams:AddToFilter(hit)
end
end
end
if pixel.BackgroundColor3 == toColor3(pixelColor) then return end
pixel.BackgroundColor3 = toColor3(pixelColor)
end
--local function postProcessPixel(pixel: Frame,uv: Vector2)
-- local pixelColor = fromColor3(pixel.BackgroundColor3)
-- pixel.BackgroundColor3 = toColor3(pixelColor)
--end
local function updatePixels()
sunPosition = lighting:GetSunDirection() * 10000
clockTime = timeToAbs(lighting.ClockTime)
for x,row in pixels do
for y,pixel in row do
updatePixel(pixel,vec2(x,y))
end
end
--for x,row in pixels do
-- for y,pixel in row do
-- postProcessPixel(pixel,vec2(x,y))
-- end
--end
end
initPixels()
while runService.Heartbeat:Wait() do
updatePixels()
task.wait(UPDATE_RATE)
end