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.
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.