I'm trying to render music notations to godot using SMuFL fonts. To do this polygons are created from the lines and curves described in the OpenType fonts, read from SixLabors Font. The current problem is how to render the polygons so that overlapping regions are excluded, like an XOR operation.
The first approach I tried is adding polygons directly to the scene, each with a shader that XORs the screen color and texture color. The problem I found in this approach is that the overlapping regions do not become transparent.
The second approach is to use Clipper library, but this does not clip polygons lying fully inside another.
The current approach is to create a separate Viewport fill with black pixels, add polygons each with a BackBufferCopy behind and holding a shader that compares color equality to simulate XOR process. Then, Light2D node is added to the scene, which takes the texture from the separate Viewport and use Sub Mode so white colors are subtracted to get intended black colors. However, the use of Light2D decreases performance by a great amount (setting one Light2D to invisible increases the fps by around 20, wow), as described in this github issue, so I need another way to render music scores, likely by performing overlap XOR operation directly on screen.
The shader script is this:
shader_type canvas_item;
uniform vec4 active_col:hint_color;
uniform vec4 same:hint_color;
uniform vec4 different:hint_color;
vec4 exclusion(vec4 base, vec4 blend){
return base + blend - 2.0 * base * blend;
}
vec4 color_dodge(vec4 base, vec4 blend){
if (blend.r == 0f && blend.g == 0f && blend.b == 0f) return vec4(0f,0f,0f,0f);
return base / (1.0 - blend);
}
void fragment() {
vec4 scrC = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
vec4 texC = texture(TEXTURE, UV);
// This doesn't work somehow
//COLOR.rgb = vec3(float(int(scrC.r * 256f) ^ int(texC.r * 256f)) / 256f,
// float(int(scrC.g * 256f) ^ int(texC.g * 256f)) / 256f,
// float(int(scrC.b * 256f) ^ int(texC.b * 256f)) / 256f);
//if (scrC == texC) {
// COLOR = new;
//}
//else COLOR = texC;
//scrC = overlay(scrC, texC);
//COLOR.rgb = scrC.rgb;
//COLOR = texC;
if (texC.rgb == active_col.rgb && scrC.rgb != texC.rgb)
COLOR.rgb = different.rgb;
else
COLOR.rgb = same.rgb;
}
The reason not to use label directly is that I need to know the bounding boxes of each notation, so I can place stems and flags, etc. to the anchors of a notehead, where the anchor is relative to the bounding box's origin. Here is an image example (The red box is the bounding box, the blue box is the overall size of the text, green line is the origin):