Now, I'm not great at geometry (never have been) but one thing I understand is raycasting. So, as a test, I decided to make a Wolfenstein-3d style raycasting renderer in Roblox, just for fun. I've got a lot of it working; including a basic camera, screen drawing (unfortunately done with frames because Roblox) and a simple raycasting setup with resolution and FOV settings. It's in one big script, including player creation, raycasting, and all that. Just run the code inside a ScreenGui.

The problem I'm having is a distortion issue on there (not the lens distortion, what I mean becomes apparent when you test it out) wherein the geometry of the raycaster doesn't seem to match with the geometry of the world. Parts clip in and out of existence, everything is stretched and distorted, and more. Like I said, I'm no good at geometry and angles, so this isn't really stuff I'm great at. Could anyone help?

Here's the full code, run it in a LocalScript under a ScreenGui.

local RES = 4
local FOV = 70

local movespeed = 50

local player = Instance.new("Part")
player.Anchored = true
player.Position = Vector3.new(0,10,0)
player.Size = Vector3.new(2,1,2)
player.Parent = workspace

local camera = workspace.CurrentCamera

local UIS = game:GetService("UserInputService")
UIS.MouseBehavior = Enum.MouseBehavior.LockCurrentPosition

game.Players.LocalPlayer.CameraMaxZoomDistance = 0.5
game.Players.LocalPlayer.CameraMode = Enum.CameraMode.LockFirstPerson
game.Players.LocalPlayer.Character:WaitForChild("HumanoidRootPart").Anchored = true
game.Players.LocalPlayer.Character.HumanoidRootPart.Position = Vector3.new(0,-20,0)


local function singleray(x, offset, ogdir)
	local ray = workspace:Raycast(player.Position, (player.CFrame.LookVector + CFrame.Angles(0, math.rad(offset), 0).LookVector) * 512)
	local dist
	local actdist
	local colormod
	local saturation
	if ray then
		actdist = (ray.Position - player.Position).Magnitude
		if ray.Material == Enum.Material.Marble then
			colormod = 0.65
			saturation = 1
		else
			colormod = 0
			saturation = 0
		end
	else
		actdist = 512
		dist = 512
		colormod = 0.65
		saturation = 0.25
	end
	
	local frame = Instance.new("Frame")
	frame.AnchorPoint = Vector2.new(0,0.5)
	frame.Position = UDim2.new(0, x, 0.5, 0)
	frame.Size = UDim2.new(0, RES, 0, camera.ViewportSize.Y*8/actdist)
	frame.BorderSizePixel = 0
	frame.BackgroundColor3 = Color3.fromHSV(colormod, saturation, 1)
	frame.Parent = script.Parent
end

local function raycast()
	for _,v in pairs(script.Parent:GetChildren()) do
		if v:IsA("Frame") then
			v:Destroy()
		end
	end
	
	local ogdir = player.Orientation.Y
	local offset = FOV/2
	local x = 0
	local sl = camera.ViewportSize.X/RES
	
	for i = 1, sl do
		singleray(x, offset, ogdir)
		offset -= FOV/sl
		x += RES
	end
end

game:GetService("RunService").RenderStepped:Connect(function(dt)
	raycast()
	
	player.Orientation += Vector3.new(0,-UIS:GetMouseDelta().X,0)
	
	if UIS:IsKeyDown(Enum.KeyCode.W) then
		player.CFrame = player.CFrame + (player.CFrame.LookVector * movespeed * dt)
	end
	if UIS:IsKeyDown(Enum.KeyCode.S) then
		player.CFrame = player.CFrame + (player.CFrame.LookVector * -movespeed * dt)
	end
	if UIS:IsKeyDown(Enum.KeyCode.A) then
		player.CFrame = player.CFrame + ((player.CFrame * CFrame.Angles(0, math.pi/2, 0)).lookVector * movespeed * dt)
	end
	if UIS:IsKeyDown(Enum.KeyCode.D) then
		player.CFrame = player.CFrame + ((player.CFrame * CFrame.Angles(0, math.pi/2, 0)).lookVector * -movespeed * dt)
	end
	camera.CFrame = player.CFrame
end)

Thanks in advance!