Raycasting and Illumination
Learn how to implement a raycasting system with SplashKit to simulate light rays and object illumination. This tutorial covers collision detection, dynamic ray length adjustment, and interactive visuals for game development or physics simulations.
Written by: Shaun Ratcliff
Last updated: 08 Dec 24
Full C# and Python code for this tutorial is still in development.
Introduction to Raycasting and Illumination
In this tutorial, you’ll learn how to implement a raycasting system that simulates illumination using SplashKit. This tutorial combines SplashKit’s physics and colour functions to show demonstrate dynamics. It will cover how to:
- Cast rays from a source to detect objects.
- Simulate illumination by varying object brightness based on ray intersection distance.
- Create an interactive environment where you dynamically adjust ray length by clicking the mouse.
By the end, you’ll understand the fundamental mechanics of raycasting and illumination, as well as how to leverage SplashKit’s built-in physics and colour functions to bring these concepts to life in your own projects.
Important SplashKit Functions Used in This Tutorial
- Point Offset By
- Vector Multiply
- Vector To
- Vector From Angle
- HSB (Hue, Saturation, Brightness) Colour
- Hue Of
- Saturation Of
- Brightness Of
Raycasting and Illumination
Raycasting can be used to simulate the behaviour of rays of light, projecting them through a scene to detect intersections with objects. It is a fundamental concept in computer graphics, physics simulations, and game development, providing a simple yet effective way to calculate line-of-sight visibility, lighting effects, and collision detection.
Illumination in the context of raycasting involves determining how objects in a scene interact with light, simulating brightness levels based on the distance of objects from the light source or the viewer. This adds a sense of realism, depth, and visual clarity, enhancing the user experience in games, simulations, and visual applications.
Why Raycasting and Illumination Are Useful
Raycasting is particularly valuable because of its simplicity and versatility. Unlike more complex rendering techniques such as ray tracing, which simulates every ray of light in a scene, raycasting focuses only on the most relevant rays. This makes it computationally efficient and suitable for real-time applications such as:
-
Visibility Determination: Raycasting can calculate which objects or parts of a scene are visible from a particular point of view. This is useful for implementing features like line-of-sight in stealth games or player detection systems in AI logic.
-
Collision Detection: By casting rays from a player or object, raycasting can identify obstacles or targets in the way, supporting mechanics like bullet trajectories, player movement restrictions, or object interaction.
-
Lighting Effects: Illumination based on raycasting simulates how light interacts with objects, providing visual cues for depth, position, and mood. For example, a flashlight effect in a horror game or lighting in a top-down dungeon crawler.
Ray Generation
In this program, rays are generated from a single source point (the mouse cursor in this case) and cast in all directions. To create this effect, we divide the full circle (360 degrees) into equal segments based on the number of rays (NUM_RAYS
).
Each ray is represented by a vector with a specific direction derived from its angle:
Ray Collisions
Once the rays are generated, the next step is to detect intersections with objects in the scene (rectangles and circles). The intersection points help determine if and where the rays interact with objects.
Collision with Rectangles
We use the ray_rectangle_intersection
function to check whether a ray intersects with the edges of a rectangle. The function calculates entry and exit points for both the x
and y
bounds of the rectangle and determines the nearest intersection.
Collision with Circles
For circles, we use the circle_ray_intersection
function. This function determines whether the ray intersects the circle within the allowed range and calculates the exact hit point.
Applying Illumination
The brightness of objects is determined by the distance between the source and the intersection point. Closer objects appear brighter, while farther objects fade. The brightness is linearly scaled based on the intersection distance relative to the maximum ray distance (MAX_RAY_DISTANCE
).
Once a ray intersects an object, its brightness is calculated, and the object’s colour is adjusted accordingly.
The hsb_color
function simplifies dynamic colour changes, allowing you to adjust brightness without modifying an object’s base hue or saturation.
The hsb_color
Function
hsb_color
is used to dynamically adjust the brightness of objects based on their interaction with rays. This function allows us to modify an object’s hue, saturation, and brightness (HSB), enabling realistic illumination effects.
When a ray intersects an object, the brightness component of its colour is calculated based on the distance of the intersection point from the light source. Closer objects appear brighter, while those farther away fade into darkness. This is achieved without altering the object’s original hue or saturation, ensuring its base colour remains consistent.
Putting it All Together
Now that we’ve covered the individual components of the raycasting and illumination system, let’s see how they work together in a full program. We’ll combine ray generation, collision detection, and dynamic illumination to create a responsive visual system. Click the Test Code in SplashKit Online
button below to load the SplashKit Online IDE and run the code yourself. The code demonstrates:
- Raycasting: Generates rays from the mouse cursor and casts them in all directions (360 degrees) to detect objects.
- Dynamic Interaction: Allows dynamic adjustment of ray length by clicking the left mouse button, cycling through predefined distances.
- Collision Detection: Detects intersections between rays and scene objects (rectangles and circles).
- Illumination Simulation: Calculates brightness for objects based on their distance from the light source, making closer objects brighter.
- Real-time Visualisation: Visualises rays and illuminated objects in real time as the mouse moves through the scene.
Conclusion
In this tutorial, we’ve implemented a raycasting system in SplashKit to simulate light and object illumination. This foundation can be expanded further for use in games or simulations, with opportunities to add new objects, refine collision logic, or explore advanced visual effects. Modify the code to fit your needs and experiment with SplashKit’s functions to explore new possibilities.