That’s a very cool and ambitious effect! You’re essentially trying to project arbitrary 3D volumes onto uneven terrain and highlight the intersected area — like decals, but in arbitrary shapes, not just quads. This telegraphing mechanic is great for strategy/ARPGs and makes for some flashy VFX.
Let’s break this down in terms of how it can be achieved in Godot 4.3, and what approaches are most viable:
The Concept
- You want to highlight areas of terrain intersected by a 3D shape (e.g. a tetrahedron or any convex mesh).
- The projection needs to clip correctly to uneven ground.
- A decal works for boxes because it handles projection and depth culling, but arbitrary shapes need a custom solution.
Feasible Techniques
In Godot 4.4, the most effective approach is shader-based projection using depth comparison and custom clipping in screen-space or world-space.
Here’s a more guided roadmap:
Option 1: Custom Depth Shader with Volume Check (Advanced, Powerful)
1. Render Your Volume Shape into a Custom Buffer (or use Depth Texture)
- In a custom Viewport, render your mesh in a flat color (depth-only ideally).
- Compare this with the main scene depth to determine intersection.
2. In Your Terrain Shader:
- Access the world position of each fragment.
- Determine if it lies within the 3D volume (e.g., tetrahedron).
- If so, blend a red highlight color.
How to check if a point is in a volume?
- For a tetrahedron: check if the point lies on the inside of all four planes (faces).
- In a shader, you can do this using dot products and barycentric coordinates.
// GDSL pseudocode
bool point_in_tetrahedron(vec3 p, vec3 a, vec3 b, vec3 c, vec3 d) {
float sign = sign(dot(cross(b - a, c - a), d - a));
return
sign(dot(cross(b - a, c - a), p - a)) == sign &&
sign(dot(cross(c - a, d - a), p - a)) == sign &&
sign(dot(cross(d - a, b - a), p - a)) == sign &&
sign(dot(cross(b - c, d - c), p - c)) == sign;
}
3. Apply a Shader to the Terrain Material
- Godot allows access to world positions in fragment shaders:
vec3 world_pos = WORLD_POSITION;
- Use the above logic to blend your red “telegraph” color where
point_in_tetrahedron(world_pos)
returns true
.
Option 2: Using a Signed Distance Field (SDF) in Shader (Easier for Complex Shapes)
If you use simple convex shapes, SDFs can determine how far a point is from the shape.
For example, a tetrahedron SDF could be written and evaluated in the terrain shader to produce a red overlay only for areas where the SDF is < 0 (i.e., inside the shape).
Godot doesn’t have built-in SDF utilities, but GLSL SDF functions are readily available for most basic shapes.
Option 3: Projective Decal Shader using a Custom Mesh
If you want something more like the Decal node behavior:
- Use a custom Material on a mesh that “projects” downwards.
- In the material, use a world-position test to blend red onto the intersected mesh surface.
E.g., create a cone, tetrahedron, or custom shape mesh with a shader that says:
“Highlight terrain that lies within this mesh’s projection.”
Bonus: You Don’t Have To Add a Render Pass
You mentioned adding a custom render pass — while possible in lower-level engines, in Godot this is usually unnecessary for this effect.
Instead, think shader-driven, where:
- The terrain shader determines whether each pixel is in the telegraph volume.
- Or the telegraph volume shader renders above the terrain and handles clipping via depth test or screen-space comparisons.
TL;DR - Suggested Pipeline for Godot 4.3
- Place your 3D “telegraph” shape in the world (e.g., a MeshInstance3D of a tetrahedron).
- Give your terrain a custom shader that:
- Gets
WORLD_POSITION
- Checks whether that point lies inside the volume (via tetrahedron math or SDF)
- Colors it red if so.
- Optional: Use a projection matrix or decal-like logic to support complex orientations.
If you want, I can provide a working terrain shader snippet that uses tetrahedron detection or go over how to calculate world-space inside-tetrahedron in detail. What kind of telegraph shapes are you mostly working with — convex only? Or arbitrary concave/complex volumes too?