Game Dev Hobbyist

A blog about my game dev hobby and various stuff.



Game Dev Hobbyist

A blog about my game dev hobby and various stuff.

Godot Quick Tip #2 - Getting the mouse cursor position in your 2D fragment shader

Want to create a pixel effect based on the position of the mouse in Godot Engine? Let me show you how.

Note: this quick tip assume that you know what a fragment shader is and how to use one in Godot.


Getting the mouse position, or coordinates, in a fragment shader is not as straightforward as one might think. There is two issues:

  • The fragment shader use normalized device coordinates, or NDC, where values are between 0 and 1, instead of pixels for the mouse.
  • The NDC origin is bottom-left while mouse coordinates are top-left.

The GD script

onready var _material = get_material()

# ...

func _input(event):
    if event.type == InputEvent.MOUSE_MOTION:
        var norm_mouse = get_viewport().get_mouse_pos()/get_viewport_rect().size
        norm_mouse.y = 1.0 - norm_mouse.y
        _material.set_shader_param("mouse_pos", norm_mouse)

This is the code you want to put in the script of the node where the effect should apply. The calculation takes place on a mouse motion event. The first thing you want to do is normalize the mouse coordinates by dividing the mouse position by the viewport size, effectively giving you coordinates between 0 and 1. Then, in order to change from a top-left origin to a bottom-left origin, you just subtract the vertical normalized coordinate from 1. Sending the value to the fragment shader is quite easy with Godot, you call the set_shader_param function of the material. Finally, a call to update makes sure that the node will be redrawn, using the new mouse coordinates.

The fragment shader

uniform vec2 mouse_pos = vec2(0.0, 0.0);

float dist = distance(SCREEN_UV, mouse_pos);

To be able to use the value in the fragment shader you have to declare a uniform with the type vec2, equivalent of a GD script Vector2. The name of the uniform should match exactly the name given to set_shader_param. After that you can use the mouse coordinates the way you want, in the example I calculate the distance between the mouse and the current fragment, or pixel, being drawn.

Written by Olivier on Friday March 3, 2017

« Creating a game with Godot Engine - Ep.8 - Levels Godot Quick Tip #3 - Black&White visual field »