Making a Spherical Dissolve Shader with Burn

godot 3D dissolve burn shader

This is my attempt at creating a Godot dissolve shader for 3D objects (for 2D, see godot 2D dissolve shader). The edges are burned so the effect looks kinda cool. It can be used where you want to hide objects based on its area. For example, objects inside certain zone will be hidden entirely and be invisible. And when they emerge from that area, they will emerge with a good animation.

It can also be used to simulate destruction in some cases. For example after a blast, or when a building is being erased in an RTS game. And, can be used in combination with a 3D grass shader to simulate grass/crops burning.

Breakdown of Shader

  1. First step is to make a simple 3D dissolve shader. We run shader on each fragment, and if the fragment lies inside a sphere, then we discard; it, else we do nothing (thus it gets rendered). To know if a fragment/pixel lies inside a sphere, we use simple math function that checks if a point is in the sphere.
  2. Second step is to take a slice of the rendered part from the mesh, near the edges where we discarded the fragments. And based on a threshold, apply burn effect on it.
  3. Third step is to (optionally) apply burn effect on the inner faces as well (the back faces), so it doesn’t look hollow from inside.

Part 1: Creating Simple Dissolve Shader

This shader creates a dissolve effect where objects appear to be “eaten away” by a sphere, with a glowing edge at the dissolution boundary. Think of it like a sci-fi disintegration effect.

shader_type spatial;
render_mode cull_disabled; // View both sides

uniform vec3 sphere_position = vec3(0.0);
uniform float sphere_radius = 1.0;
uniform float burn_threshold = 0.1;

uniform sampler2D noise_texture;
uniform float noise_strength = 0.1;
uniform float noise_scale = 1.0;
  • sphere_position: Where the dissolve effect originates from (default at center)
  • sphere_radius: How big the dissolve sphere is
  • burn_threshold: How thick the glowing edge effect should be
  • noise_texture: A texture that adds randomness to the edges
  • noise_strength: How much the noise affects the edge (higher = more jagged)
  • noise_scale: How “zoomed in” the noise pattern is

In the fragment() function:

void fragment(){
vec3 world_pos = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;

This converts the vertex position to world space, so our effect stays consistent as the camera moves.

float dist = distance(world_pos, sphere_position);

This measures how far each point on the object is from our dissolve sphere’s center.

// Adding Noise for Irregular Edges
vec2 noise_uv = (world_pos.xy + world_pos.yz + world_pos.xz) * noise_scale;
float noise = texture(noise_texture, noise_uv).r * 2.0 - 1.0;

This creates irregular edges by:

  • Creating UV coordinates from the world position
  • Sampling the noise texture
  • Converting the noise from 0-1 range to -1 to 1 range for better effect
// Applying the Dissolve Effect
float noisy_radius = sphere_radius + noise * noise_strength;
float sphere_dist = dist - noisy_radius;

if (sphere_dist < 0.0) {
    discard;
}

This is where the dissolve happens:

  • Adds noise to the sphere’s radius
  • If a point is inside the noisy sphere, it’s discarded (becomes invisible)
// Creating the Simple Burn Effect
if (sphere_dist < burn_threshold) {
    float burn_factor = sphere_dist / burn_threshold;
    float burn_noise = texture(noise_texture, noise_uv * 2.0).r * 0.5;
    burn_factor = mix(burn_factor, burn_factor * (1.0 + burn_noise), 0.5);
    
    ALBEDO = vec3(1.0);
    EMISSION = vec3(1.0) * (1.0 - burn_factor);
    EMISSION *= 1.0 + burn_noise * 0.5;
}

This creates the glowing edge:

  • Checks if we’re within the burn threshold distance
  • Creates a smooth transition from full glow to no glow
  • Adds some noise to the burn effect for more realism
  • Sets the color (ALBEDO) to white
  • Adds emission for the glow effect
// rest of Normal pixel Rendering
else {
    ALBEDO = vec3(0.5); // Currently render just a gray color
}

} // Closing fragment()

For parts not affected by the dissolve or burn:

  • Renders with a default gray color (will be customized later).
godot dissolve shader
This is how the effect looks so far. We will later convert these white edges to a burning effect.

Part 2: Adding Burning Effect to Dissolved Edges

Now we convert the basic burn (white colored as seen above), to a real burn. We will use a neon function to make it look good.

  1. Add New Uniform Variables
// Add these new uniform declarations after the existing ones
uniform vec3 neon_base_color: source_color = vec3(0.2, 0.5, 1.0);
uniform vec3 albedo_color: source_color;
  1. Add the Neon Effect Function Add this new function before the fragment() function:
vec3 calculate_neon_effect(float value, vec3 base_color) {
    float ramp = clamp(value, 0.0, 1.0);
    vec3 neon_color = vec3(0.0);
    
    // Layer 1: Intense core
    ramp = ramp * ramp;
    neon_color += pow(base_color, vec3(4.0)) * ramp;
    
    // Layer 2: Mid intensity
    ramp = ramp * ramp;
    neon_color += base_color * ramp;
    
    // Layer 3: Bright center
    ramp = ramp * ramp;
    neon_color += vec3(1.0) * ramp;
    
    return neon_color;
}
  1. Modify the Fragment Function Replace the original burn effect code with these changes:

a. Add default material properties:

// Add after sphere_dist < 0.0 check
ALBEDO = albedo_color;
METALLIC = 0.0;
ROUGHNESS = 1.0;
EMISSION = vec3(0.0);

b. Replace the original burn effect code with:

if (sphere_dist < burn_threshold) {
    float burn_factor = sphere_dist / burn_threshold;
    
    float burn_noise = texture(noise_texture, noise_uv * 2.0).r * 0.5;
    burn_factor = mix(burn_factor, burn_factor * (1.0 + burn_noise), 0.5);
    
    // Calculate and apply neon effect
    vec3 neon = calculate_neon_effect(1.0 - burn_factor, neon_base_color);
    EMISSION = neon * 2.0;
}
  1. Remove Old Burn Effect Code Remove these parts from the original shader:
  • Remove the white ALBEDO setting (ALBEDO = vec3(1.0);)
  • Remove the old emission calculations
  • Remove the burn color variation code
godot 3d burn shader
This is what we achieved so far. You can play with the color values for burn, to make it different (such as purple, green or blue).

Step 3: Add Neon Effect to Back Faces as Well

Add New Uniform Variable: Add this after your existing uniforms:

uniformfloat inner_face_neon_intensity = 0.86;
  1. Add Back Face Detection and Effect: Add this code block at the end of the fragment() function, after the burn effect code:
// Additional neon effect for back faces
if (!FRONT_FACING) {
    vec3 back_face_neon = calculate_neon_effect(inner_face_neon_intensity, neon_base_color);
    EMISSION += back_face_neon * 1.5;
}
3D sphere mask cutoff shader godot
This is how it looks so far.

Optional: Add Uniforms Standard Material Properties

So far we cannot control metallic, specular, diffuse, and so on. So you can add additional uniforms to handle them, so the shader behaved as a standard 3D material, with this burn effect.

Thank you for reading <3

Images

Godot neon effect burn
godot 3D dissolve shader
godot burn and dissolve shader

Leave a Reply

Your email address will not be published. Required fields are marked *