Help me understand MODEL_MATRIX in 2D fragment shaders

Godot Version: 4.2.2 Stable

Question

Hi!
For the past two days I’ve been bashing my head against the MODEL_MATRIX shader built-in and even after reading through what seems like all the related posts on the internet and tearing the documentation apart, I couldn’t implement it successfully.

What I’m trying to do:

I want to have a fragment shader applied on a Sprite2d material (The Sprite2d in question is the godot logo), that would make a part of the logo between global x 95.0 and 105.0 more red.

My attempt:

I have written this code and to the extent of my knowledge, it should work like that:

shader_type canvas_item;

varying mat4 modelMatrix;

void vertex() {
	modelMatrix = MODEL_MATRIX;
}

void fragment() {
	vec2 localSpaceVector = VERTEX;
	
	vec2 globalSpaceVector = (modelMatrix * vec4(localSpaceVector, 1.0, 1.0)).xy;
	if(globalSpaceVector.x > 95.0 && globalSpaceVector.x < 105.0){
		COLOR.r = 1.0;
	}
}

What happens instead:

The shader is being applied wayyyy out in the distance:

So I haven’t given up on trying since posting, and in a seeming bout of madness I came up with something that achieves my original goal, which I believe might prove useful to someone, sometime in the future. Here’s what I did:

This piece of code, allows you to use global coordinates (editor coordinates) of each pixel in a fragment shader in 2D:

shader_type canvas_item;
//Render mode set to using global scene coordinates
render_mode world_vertex_coords;

//Preparing varyings to use between functions
varying vec4 pos;
varying mat4 canvasMatrix;

void vertex() {
	//Save the origin point coordinates of the Node2D, in GLOBAL COORDINATES
	pos = vec4(VERTEX, 0.0, 0.0);
	//Save the matrix that transforms coordinates from GLOBAL to CANVAS
	canvasMatrix = CANVAS_MATRIX;
	
	//(OPTIONAL) Modify the origin point by some offset (values are opposite
	//to those in the editor, ie. 5 in the editor is -5.0 here)
	//pos.x -= 0.0;
	//pos.y -= 0.0;
}

void fragment() {
	//The width of the camera in editor pixels (set this manually)
	float cameraWidth = 320.0;
	//Calculate the ratio by which editor pixels are divided in the CANVAS
	float resizeRatio = SCREEN_PIXEL_SIZE.x*cameraWidth;
	//Convert the origin point vector from GLOBAL to CANVAS coordinates
	vec4 screenspaceVector = canvasMatrix * pos;
	//Resize the new vector by the resize ratio
	vec4 globalPos = resizeRatio * screenspaceVector;
	//The conversion is complete. globalPos now indicates the position
	//of the currently evaluated pixel in the fragment() function, in global
	//coordinates. It can also be compared to other vectors in global coordinates,
	//without the need to convert them.
	
	//In this example, a red circle with a diameter of 5px will be rendered
	//on top of this sprite, with a center at (0,0)
	if(
		distance(globalPos, vec4(0.0, 0.0, 0.0, 1.0)) < 10.0
	){
		COLOR = vec4(1.0, 0.0, 0.0, 1.0);
	}
}

In all honesty, despite my best attempts at commenting everything in the code, I still do not really understand how or why it works. Feel free to contact me on the Godot discord (@frost1993.) if you have any questions about it, I’ll try to help.

Since I achieved my original goal, I’m closing down the post.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.