Ray Tracing Module #2

Absolutely, you read the title right—another exciting and impactful update is here! [prior post]

In this post I am not only going to discuss the things that changed but also the future and release of this module.

What has changed?

  • parcial rewrite of the Render-Class:
    – The Render-Class now supports sampled rendering
    – Improved syntax for better user-friendliness
    – Optimized function calls with reduced data exchange
    – Enhanced maintainability
    – Added structure to support future features

  • Actors:
    Actors are now created in Folders, accessible directly from the created Render instance
    Actors can be reconfigured after creation, allowing for easier on-the-go adjustments

  • RenderSettings:
    – RenderSettings now store a RaycastParams for user defined raycasting
    – number of Actors, rays per pixel and rays per light-source are now set in the RenderSettings rather than passed via Render() method call

New code-structure:

local RayTracer = require(game.ReplicatedStorage.RayTracer) 
local renderSettings = RayTracer.newRenderSettings()

-- config of the settings
renderSettings.renderFrame = someUiFrame
renderSettings.renderDistance = 500
renderSettings.raysPerLight = 3
renderSettings.raysPerPixel = 1
renderSettings.actors = 20
renderSettings.useSampling = true
renderSettings.antiAliasing = true
renderSettings.raycastParams.FilterType = Enum.RaycastFilterType.Exclude
renderSettings.raycastParams.FilterDescendantsInstances = {game.Workspace:WaitForChild("DosenSuppe2_0")}

local renderHandler = RayTracer.newRender(renderSettings):init()

-- creating/ loading a new shader
local shaderHandle = renderHandler:LoadShader(function(pixelColor: Color4, pixelPosition: Vector3, pixelNormal: Vector3, frameResolution: Vector2)
	local uv: Vector2 = pixelPosition / frameResolution
		
	return pixelColor * uv.X
end)

-- event that fires when a render finished
renderHandler:OnFinished(function(renderTime: number, renderIteration: number)	
	renderHandler:Draw()
end)

someButton.Activated:Connect(function()
	renderHandler:Render()
end)

New Renders!

Here are some new renders using sampled-rendering:

Screenshot 2024-08-02 212629
Screenshot 2024-08-25 191040
Screenshot 2024-08-27 212707


One step closer to “Real-Time Raytracing”.
An image with a resolution of 70x70 runs at an average of 35FPS now! That is if sampled-rendering and soft-shadows are turned OFF.
For reference, the prior versions struggled to stay in the double digits FPS with same configuration!

What coming in the future?

  • Post processing:
    – A new feature will allow custom post-processing effects to be added to a finished render, including custom shaders
    – The release date for this project is uncertain as development falls short due to private reasons, but it is scheduled for release in late September

I am thrilled to read your feedback!
@TheRealANDRO (I thought you would be interested in this update)

13 Likes

Literally higher than my normal FPS when I play roblox

Sounds very cool, but I sadly don’t know anything about raytracing :sob:

2 Likes

Ray tracing is a method used in computer graphics to create realistic images by simulating how light works in the real world.

  1. a ray is casted from the camera into the world
  2. the ray hits an object
  3. using the direction of the ray and the surface-properties of the object we can simulate reflections, refractions and more
  4. another ray (but not limited to a single ray) is casted to light-sources to calculate how much light hits the given point on the object. These rays are responsible for creating (smooth) shadows

These 4 steps apply for every pixel in an image.

If you are interested in how it works on a more technical level I can suggest you this paper.

1 Like

Thanks for the explanation! Although now I’m confused on the difference between raytracing and raycasting, because I’ve heard people call what you’ve described raycasting. Is there a difference between the two, or are they just different ways of talking about the same thing?

(I’ve also heard of raymarching, but I have even less idea what that is lol)

Raycasting:

Raycasting is faster but offers less detail as it stops at step 2. : a surface has been hit. Meaning you cannot simulate reflections, refractions). Furthermore, raycasting casts not necessarily a ray per pixel, rather a ray per row or column of pixels.

Raytracing:

Raytracing usually follows physical properties of light - as described by the 4 steps (simplified). Raytracing casts a ray from each pixel in a scene and it even casts multiple rays per pixel for greater detail.

Raymarching is an optimization technique to speed up ray-tracing.

I hope this helped you out.

1 Like

I see, that makes alot more sense now! :grinning:

1 Like

how are you manipulating individiual pixels on that gui tho?

I am using an EditableImage-Instance to draw the result onto the screen.

oh right, those exist. i assume doing this in roblox was very challenging considering u cant directly access gpu and other optimization techs, cool stuff bro

1 Like

Great job on the update! You’re literally making ray-tracing on Roblox possible lol.
However I fear that you might be starting to run out of optimization methods to use, so I don’t think you’ll reach too far due to Roblox still for some reason not giving us access to GPU.

Though, keep on improving it! I’m waiting for future updates to see where this project will go.

1 Like

Shader sneakpeak:
image

I got one more thing that can be improved, that is migrating to buffers rather than using tables to store the render-data.
Yes, I have used tables for the entire time. Buffers would decrease the memory usage for sure…
Well, that is if implemented correctly… ehhh
image

Give it a shot! That might improve it a lot. If it’s even possible, maybe you can use the bit32 library, though I don’t know if that’ll be useful.

1 Like

This looks really awesome! I myself have tried recreating this and what I did to not use EditableImages was to instead create beams on every row of the face with differing light emissions, transparency gradient and color depending on a nearest light source. It was EXTREMELY hard to code and also looks pretty janky but im sharing this in hopes you can use it somehow :V

1 Like

I am very interested! I hope you will be able to optimize a decent level for FHD resolution

1 Like

With the currently available technology that ROBLOX provides, it’s simply impossible to achieve faster render times.

Although the rendering is running in parallel, the CPU simply isn’t made for those types of mass operations. Having access to the GPU would immediately fix the slow render time; however, I think that ROBLOX is far from implementing such an API.

I tried rendering a 1920x1080 image, however, my studio crashed more than 4 times, so I settled with a sampled 1000x1000 image.

rays per pixel: 1
rays per light: 3
render distance: 35 studs
iterations: 50
total render-time: 23.25335 seconds
fastest render-time: 0.433823199942708 seconds
slowest render-time: 0.5374267000006512 seconds
avg render-time: 0.44557239999994636 seconds

the same image with no Anti-Aliasing and no sampling:
total render-time: 0.3714971999870613 seconds
iterations: 1

List of my optimization techniques:

  • batch processing
  • multi-threading (parallel lua)
  • implementation of buffers
  • custom Color4 class
  • custom (vector) math library
  • using native lua math library
  • sampled rendering (enabling better quality other multiple frames)
1 Like

I hope that roblox will update their engine after all… There are few opportunities

3 Likes