How would i create a pixel based rendering gui?

im trying to create a gui, that takes what ever you are seeing, and put it into gui. People kept telling me to use raycast, but a guy like me that knows nothing about raycasting. cant do that. I also couldn’t find any source of something like this. Help would be greatly appreciated.

basically, im trying to achieve this effect on this game:

5 Likes

My only idea of how this was made was using a SurfaceGui in which it contains frames and sprites and lots and lots of image labels. I joined the game with @C_Sharper and managed to think of this as one way to do it, but it’s very complicated.

edit: I looked over at the person’s decals and found this -

So yeah, ImageLabels and sprites are most likely gonna be your answer here.

2 Likes

but how did they get it to be 3d? the game doesn’t use viewport frames. So i dont really understand how they would get a flat image, and somehow make it 3D in a custom engine like this

To be honest, I’m not really sure. All I did as of now was just check that it was ImageLabel’s used. It’s a very complex system it seems like (obviously), but the engine itself, I don’t really know how it’d work.

perhaps it’s some sort of rectoffset or rectscale system? wow this is really complex hahahahahha

It does require raycasting, but also to sort the colors you need to raycast in multiple areas of the camera’s position. This means you’d have to somehow have the pixels of your screen match with how many raycasts you’re sending plus receiving the color and updating that every frame or so. You should learn more about Ray.new and the CurrentCamera instance before trying to do this.

Adding onto what I said (and looking at the game), you will also need knowledge of how to use the Rect properties of an ImageFrame to correctly scale the wall’s image. If you want to have a custom GUI that has frames in which act like walls, you would need to create a gui and a custom raycasting function for your raycasted walls. Learn about how to make a simple raycast maze with 2D objects (perhaps in another coding language so you can interpret it and make it in lua), then try to pull this off or experiment.

I could be wrong, but it seems like they may be using a ViewportFrame to render the parts?

no, they used raycasting. and a bunch of frames as pixels. i mean, its in the title. Viewportframes don’t really need raycasting. plus the resolution would be a lot higher if they did use viewports

You can lower the resolution of surface guis. It doesn’t have to look nice on them. You can make them as big or small as you want using pixel density (PixelsPerStud).

Yes, but i know this because its specifically designed to use raycast to render a world. like i said before, its in the title of the game. “3D” Raycast Renderer. Also that game was made before viewportframes were even a thing!

That’s a very good point. I’m really tired and didn’t really read the name of the game, I just clicked and clicked play while watching YouTube.

There’s a tutorial on there somewhere where someone made a raycasting game, but it wasn’t in lua so trying to convert it over would be a little challenging.

Edit: I found it, it was by “The Coding Train” on YouTube. It was made in Javascript.

well, thats an issue, because i dont know any other scripting language, except for a bit of python.

After a few struggles iv’e managed to recreate this effect!

It doesn’t look as good and doesnt support textures, but at least it has shading!

3 Likes

What exactly did you do? Can you send the source?

well, i didnt exactly 100% make the ui. Basically, i grabbed a very old renderer from 2012 (credit to su8) and i fixed it up, and improved it! Also depending on the device you are using, this thing can run up to like 15fps. but since i have a toaser pc, it runs at 3fps. :sweat_smile:

heres the original place with the original ui: Ray tracing camera - Roblox

And if you'd like to see the source code
player = game:GetService("Players").LocalPlayer
repeat wait() until player.Character
Char = player.Character
HRP = Char:WaitForChild("HumanoidRootPart")

wait(0)
Ambient = script.Parent.Ambient
Light = game.Workspace.Light --known light source
pixel = 60 --the pixels to be generated and rendered
size = 10 --pixel size
sky = 1
length = 100 --view range
debug = false --if true the script will handle with the old pixels rather than creating new ones
function tint(col,rat) 
	r = 1-col.r
	g = 1-col.g
	b = 1-col.b
	return Color3.new(r*rat,g*rat,b*rat)
end
function shade(col,rat)
	r = col.r
	g = col.g
	b = col.b
	return Color3.new(r*rat,g*rat,b*rat)
end
function color3add(col,col2)
	return Color3.new(col.r+col2.r,col.g+col2.g,col.b+col2.b)
end
function interpolate(col,col2,rat)
return Color3.new(col.r*(1-rat) + col2.r*rat,col.g*(1-rat) + col2.g*rat,col.b*(1-rat) + col2.b*rat)
end
function interpolateT(col,col2,rat,val)
return col*(1-rat) + col2*rat
end
function reflect(vector3,norm)
	norm = norm or Vector3.new(0,1,0)
	return vector3 - ( 2*norm*vector3:Dot(norm))
end



function GeneratePixels()
	for x=0,pixel-1 do
		wait()
		for y=0,pixel-1 do
			fr = Instance.new("Frame")
			fr.Position = UDim2.new(0,x*size,0,y*size)
			fr.Size = UDim2.new(0,size,0,size)
			fr.BackgroundColor3 = Color3.new(x,y,0)
			fr.BorderSizePixel = 0
			fr.Name = x .."/".. y
			fr.Parent = script.Parent.p
			fr.ZIndex = 3
		end
	end
end
if not debug then
	GeneratePixels()
end

while true do --start the camera loop
	wait(0.1)
	c = CFrame.new(game.Workspace.CurrentCamera.CoordinateFrame.p,game.Workspace.CurrentCamera.Focus.p)
		for x=pixel-1,0,-1 do
			for y=pixel-1,0,-1 do
				dir = c*CFrame.new((pixel/2-x)*(20/pixel*.1),(pixel/2-y)*(20/pixel*.1),-1) --with default 20 pixels .1 step
				ray = Ray.new(c.p,(dir.p - c.p).unit * length) --view ray
				part,point = game.Workspace:FindPartOnRayWithIgnoreList(ray, {Light, Char})
				r,g,b = 0,0,0 --brickcolor
				rr,rg,rb = 0,0,0 --reflection color
				r = 0 --reflection ratio
				shade = 0
				if(part)then
					color = part.BrickColor.Color
					if(part.Name == "Light")then
						r,g,b = r+color.r,g+color.g,b+color.b
					end
					ray2 = Ray.new(point,(Light.Position-point).unit * Light.Range.Value) --light ray to view point
					part2 = game.Workspace:FindPartOnRayWithIgnoreList(ray2, {Light, Char})
					ratio = (Light.Position - point).magnitude/Light.Range.Value
					if(part2~=nil)then
						shade = 0
					end
					if(ratio>1)then
						ratio = 1
					elseif(ratio<0)then
						ratio = 0
					end
					if(part.Name == "Water")then --add reflection values
						ref = reflect(dir.lookVector)
						ray3 = Ray.new(point,ref*length)
						part3,point3 = game.Workspace:FindPartOnRayWithIgnoreList(ray3,{part})
						if(part3)then
							color2 = part3.BrickColor.Color
							rr,rg,rb = rr+color2.r,rg+color2.g,rb+color2.b
							r = part.Reflection.Value
						end
					end
					if(shade==0)then --light wasn't blocked
						if(rr~=0 and rg~=0 and rb~=0)then --add the reflection to the final color
							r = interpolateT(color.r*(1-ratio),rr,r,"r")
							g = interpolateT(color.g*(1-ratio),rg,r,"g")
							b = interpolateT(color.b*(1-ratio),rb,r,"b")
						else --no reflection
							r = color.r*(1-ratio)
							g = color.g*(1-ratio)
							b = color.b*(1-ratio)
						end
					end
				else 
					if(sky == 1)then
						r = 0 --default sky
						g = 153/255
						b = 204/255
					end
				end
				r = r * Ambient.Value.r
				g = g * Ambient.Value.g
				b = b * Ambient.Value.b
				script.Parent.p[(pixel-1)-x .."/".. y].BackgroundColor3 = Color3.new(r,g,b)
			end
		end
		
		Light.Position = HRP.Position
		
	end


--Originally written by su8
--July 2012
7 Likes