How to get the actual vec2 screen-space coordinates from mat4 SCREEN_MATRIX in a canvas item vertex shader?

Godot Version

4.2.1 stable

Question

I’m trying to get the vec2 x and y screen space coordinates of a vertex from (-1,-1) to (1,1). In the docs the description of SCREEN_MATRIX seems to be exactly what I want:

in mat4 SCREEN_MATRIX Canvas space to clip space. In clip space coordinates ranging from (-1, -1) to (1, 1).

Except that it returns a mat4 and I don’t know how to “convert” that into a simple vec2 with just the x and y coordinates as described in the docs. How would I do that?

You can’t convert such a matrix into coordinates.

When you have two different coordinate systems, you can transform coordinates from one coordinate system into the other coordinate system using such a matrix.

I understand the docs in the following way:
The mat4 is used to transform coordinates between the following two coordinate systems:

  • The coordinate system of the canvas space
  • A generic coordinate system that ranges from (-1, -1) to (+1, +1)

If you have a CanvasItem and want to know the screen (as in the actual hardware-display) position (relative to the main window) of a point in the local coordinate system of the CanvasItem, then you can do this in GDScript:

func calc_screen_position():
    var local_pos = Vector2(x, y)
    var screen_pos = get_viewport().get_screen_transform() * get_global_transform_with_canvas() * local_pos

For more details on the coordinate systems, see Viewport and canvas transforms — Godot Engine (latest) documentation in English

I’m not sure I follow. What does that has to do with the vertex shader? Are you saying I should just use an uniform to pass the coordinates from gdscript to the shader? Is it not possible for the shader itself to know the screen coordinates without passing that value from the outside?

I thought the SCREEN_MATRIX contained that value and I was just not understanding how to use it. Was my assumption incorrect?

Hey there, not sure if I fully understand your question because it differs from the topic title. In case you want to have the vertex coordinates in clip space what you need to do is transform the VERTEX built-in (which is a vec2) from Local space (the space it comes in) into clip space. To do this you multiply the necessary matrices with the VERTEX and assign it to a custom variable:

vec new_coord = (MODEL_MATRIX * CANVAS_MATRIX * SCREEN_MATRIX) * VERTEX

So you first transform from Local to world space and then from world to camvas space and then from canvas to clip space.