How to get the size of the screen in the vertex function

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Billard

I’m currently writing a very simple parallax shader. Here’s the code:

shader_type canvas_item;

uniform vec2 centre = vec2(640,360);
uniform vec3 facteur = vec3(0.0);
uniform bool sol = false;

void vertex() {
	vec2 position = vec2(0.0);
	if (sol) {position = (WORLD_MATRIX*vec4(VERTEX, 0.0,1.0)).rg}
	else {position = (WORLD_MATRIX*vec4(1.0)).rg}
	vec2 posrelative = (position-centre) / (centre*2.0);
float perspective = max(1.0 + posrelative.y * facteur.z, 0.0);
	vec2 decalage = vec2(centre * facteur.xy * posrelative * 0.5) * perspective;
	VERTEX = VERTEX * perspective + decalage;
}

Its purpose is to add some depth to 2D games where the usual ParallaxLayer nodes aren’t useful (eg SMK / MKSC styled 2D race game). Here’s how it works (+ translation):

Centre = Center : Position in the screen where all nodes get their original scale back. In a 2D race game it would be the position of the player car.

Facteur = Factor : How much the parallax affects the nodes’ position (x,y = parallax layer motion scale) and scale (z).

Sol = Floor : How the shader scales the vertexes. If your sprite is a landscape element (a tree, a plant), scaling the sprite to is sufficient create a 3D effect, but if you are working with the road sprite or anything on floor, it should be “flattened” or it’ll look weird.

I feel like this shader could be improved in many ways, but the first thing I’ll like to know is if it’s possible to get the screen size from the vertex function; or else, you’ll have to change the “centre” uniform each time the screen is resized (which can be troublesome, even if you use the same material for all your sprites).
If it’s possible, then the “centre” uniform could either become useless, either become relative: for example centre = vec2(0.5,0.5) or centre = vec2(0.5,0.8) considering the player’s kart might not be in the true center of the screen.
If it’s not possible it would be nice if anyone could explain me what exactly the constants WORLD_MATRIX, PROJECTION_MATRIX etc do represent. The line to get the absolute position of the sprite in the screen was just pasted from the docs, I still don’t get a 4x4 matrix actually is. (3x3 is fine, but 4x4?)
Feel free to use / edit this btw, I think this basic shader could become useful in many situations.

:bust_in_silhouette: Reply From: Zylann

According to the reference, there doesn’t seem to be any way to get the size of the screen in the vertex shader: https://docs.godotengine.org/en/stable/tutorials/shading/shading_reference/canvas_item_shader.html#vertex-built-ins

In the fragment shader, there is SCREEN_PIXEL_SIZE, which inverted would give you screen size.

I’m not fully understanding everything here, but It should be noted that the vertex shader’s work is mostly to convert from local, world, camera and canvas positions to normalized coordinates (using the matrices to clip space I think). And in normalized coordinates, the center is always (0, 0), or (0.5, 0.5) (I don’t remember which).

I don’t understand why a 4x4 matrix would be used in a canvas_item shader, though it’s just how it is for some reason.
They are explained here https://docs.godotengine.org/en/stable/tutorials/shading/shading_reference/canvas_item_shader.html#vertex-built-ins
Though it is implied that you already know vertex shader basics.
WORLD_MATRIX converts local space to view space directly (local to world, world to view), so it combines both the transform of the 2D object AND the camera transform.
PROJECTION_MATRIX converts the output of the previous into normalized coordinates that the rest of the graphics pipeline expects, I suppose. Though I never saw examples of its usages. I assume that one somehow contains screen size information in a different form, so it would require extra computations from you to get it back (I dont know how).

Obviously an easy way to get screen size is to simply pass it with a uniform parameter and a script.