Shadow Casting is a method to achieve high-quality dynamic shadows in 3D graphics in real-time.
The essence of the method is a novel optimization of how ray-triangle intersection tests are performed, allowing real-time, fully dynamic shadows with ray-traced quality to be rendered without requiring specialized RT hardware.
Since no specialized RT hardware is required — the algorithm utilizes only the standard rasterization pipeline — the method is applicable to all major 3D graphics APIs, including Vulkan, OpenGL, and DirectX.
It is designed for easy integration into any existing engine; it is essentially "plug and play." Furthermore, because it utilizes the same vertex buffers already used for rendering the scene, there is no need for additional buffers or complex acceleration structures.
Time to implement: minutes.
Into any existing engine.
The implementation is extremely simple; it requires only minimal, standard CPU-side code to execute the shaders.
The first input consists of raw geometry, where world-space vertex coordinates are fed into the vertex shader via a standard vertex buffer. The second input is pre-rendered geometry information — specifically, world-space positions from the G-buffer passed to the fragment shader as a texture.
An additional MVP matrix should be provided to the geometry shader, as well as the current camera position and the current light position.
The output is a texture containing a binary shadow mask, which can be further processed as needed. For example, a depth-aware blur can be applied to simulate soft shadows. In its base form, the algorithm produces high-quality hard shadows.
How It Works
The implementation utilizes a standard pipeline consisting of Vertex, Geometry, and Fragment shaders. (Note: Mesh Shaders may be used in place of the Geometry stage on supported hardware).
The core of the algorithm lies in the optimization of Ray-Triangle intersection. In standard implementations, calculating these intersections becomes impractical because the system must evaluate every potential point. Shadow Casting optimizes this by focusing on where shadows are physically likely to occur. By generating specific shadow projections, the system "pre-filters" the scene—effectively making it viable for real-time use.
More technically, the method utilizes the Geometry stage to expand triangle data into a set of projection planes. These are passed to the Fragment stage, where the "shadow test" is performed as a local calculation rather than a global search.
The shader files can be found via the link at the bottom of this page. Note that this is not an open-source project; please refer to the license.
Performance
Tested across various configurations — from high-end hardware (RTX 4070 Ti) to legacy systems (GTX 750 Ti) — the performance remains consistent, assuming a proportional triangle count for each device.
The load is view-dependent and light-position dependent. It is also dependent on shadow casting distance, so that parameter has to be tuned. Currently, it is set as a constant for simplicity, but other approaches are advisable.
Back-face culling must be enabled for this implementation, as it is baked into the core principle. Depth write and depth test should be enabled for optimal performance. Additional culling is performed in the geometry shader (early return on triangles facing away from the light) to reduce overhead. In order to handle double-sided geometry (e.g., foliage), some simple logic must be performed instead of an early return.
While the method handles non-optimized geometry, it is recommended to use simplified geometry for large scenes (exceeding 500k triangles) to avoid unnecessary computational overhead.
Both directional and omni-directional lights are supported. No multiple passes are required; a single pass per light suffices for both types.
The method does not suffer from common shadow map issues, such as shadow acne, bias, or resolution limits. Note that some self-shadowing artifacts on curved surfaces may occur, revealing the underlying flat geometry of the object.
Many improvements can be made on the top of the base implementation - the project is provided intentionally in its current form. In addition to already mentioned soft shadows, it can also handle transparency and semi-transparency due to its ray-based nature.
Also, decoupling from main framebuffer rendering resolution is possible, which can be a game-changer in certain scenarios. And many more...
For any use beyond evaluation, such as integration into commercial or non-commercial products, scientific papers, games, or other systems, please contact via the provided email to obtain a formal License Agreement.
e-mail: dvinfoct@yahoo.com
Official distribution:
Vasilev, A. (2026). Shadow Casting: Real-time dynamic shadows for 3D graphics. Zenodo. https://doi.org/10.5281/zenodo.21238489