• Godot HelpShaders
  • How to make a shader for invisible objects to visible in some spots?

Hello. I want to create invisible object that will turn visible on the spots where the player is close to, like in the image.
How can I achieve this? Doesn't need to be anything fancy.

  • cybereality
    Megalomaniak

    Using a combination of both, I have figured it out.
    The only thing to note is that player_pos has to be updated constantly in gdscript.

    Shader code:

    shader_type spatial;
    
    
    uniform vec4 _color : hint_color = vec4( 0.2, 1.0, 1.0, 1.0 );
    uniform float sphere_size = 3.0;
    uniform vec3 player_pos = vec3( 0.0, 0.0, 0.0 );
    
    varying vec3 world_vertex;
    
    
    
    void vertex( )
    {
    	world_vertex = (WORLD_MATRIX * vec4(VERTEX, 1.0)).xyz;
    }
    
    
    void fragment( )
    {
    	
    	float min_dist = min(
    		length( player_pos - world_vertex ), 10);
    	
    	
    	ALBEDO = _color.rgb;
    	ALPHA = clamp(_color.a * sphere_size - min_dist, 0.0, 1.0 );
    }

You can do that with a shader.

The easiest way to start is to pass the player position into the shader as a uniform vec3.

Then in the spatial material, you can create a sort of sphere in code that affects the visibility.

For example:

uniform vec3 player_position;

void fragment() {
    if (distance(player_position, pixel_position) < 10.0) {
        ALBEDO = vec3(0.0, 0.0, 1.0);
    } else {
        ALPHA_SCISSOR = 0.5
        ALPHA = 0.0
    }
}

You will just have to calculate pixel_position yourself, as that is not a built-in value, I just made it up.

But there are equations to calculate the world space position of a pixel giving the screen 2D pixel value and the depth value.

    cybereality
    Megalomaniak

    Using a combination of both, I have figured it out.
    The only thing to note is that player_pos has to be updated constantly in gdscript.

    Shader code:

    shader_type spatial;
    
    
    uniform vec4 _color : hint_color = vec4( 0.2, 1.0, 1.0, 1.0 );
    uniform float sphere_size = 3.0;
    uniform vec3 player_pos = vec3( 0.0, 0.0, 0.0 );
    
    varying vec3 world_vertex;
    
    
    
    void vertex( )
    {
    	world_vertex = (WORLD_MATRIX * vec4(VERTEX, 1.0)).xyz;
    }
    
    
    void fragment( )
    {
    	
    	float min_dist = min(
    		length( player_pos - world_vertex ), 10);
    	
    	
    	ALBEDO = _color.rgb;
    	ALPHA = clamp(_color.a * sphere_size - min_dist, 0.0, 1.0 );
    }

      SuperDoomKing The only thing to note is that player_pos has to be updated constantly in gdscript.

      Yes, I didn't think to mention it since I thought it obvious enough. I assume same was the case with cybereality's post.

      a month later

      I have another questions.
      How do I make the shader effect the material/shader underneath?

      I want to make the invisible shader work for various textures,
      but I don't want to make a 100 versions to accommodate for those different textures.