How Can I Set Any Single Color To Be Transparent?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By davidpgil
:warning: Old Version Published before Godot 3 was released.

I have an image that has no alpha channel with a logo in the middle and the rest of the image is hot pink (red 255, green 255, blue 0). I want to make that color transparent in Godots viewport and when the game is run. How do I do that?

I know I can just save a PNG with alpha transparency, but I have some reasons I do not want to do this. I want to to “key out” or “chroma key” the hot pink color so it is not visible at all.

If this needs to be done with a script, please help me find what I need to look at in order to do this.

Thanks in advance for any help.

I know I can just save a PNG with alpha transparency, but I have some reasons I do not want to do this.

Using alpha transparency in PNGs is a better idea – image editing in a game engine is rarely a smart thing to do, and Godot does not have functionality to display a single color value as transparency.

This can be done automagically using ImageMagick. For example, you could use this ImageMagick command, looping over PNG files with a constant color as transparency key (here, it’s cyan):

mogrify -transparent "rgb(0, 255, 255)" image.png

Note that this will overwrite the original files, use convert instead of mogrify to be able to specify a destination file name.

Calinou | 2017-10-07 12:08

Thank you for your thoughtful response.

My hope was to take advantage of indexed color graphics. I have worked in creating gameboy and nintendo ds games in the past and I want to work with images in a very similar way where I could play with color indexes of a small group of colors to create certain visual effects. I know these days people don’t use indexed color graphics except for animated gifs, but I want to retain this “feel” for my project.

Again, I appreciate your response because it grants me more information to play with with. Also, imagemagick is awesome! tip of the hat to you.

davidpgil | 2017-10-07 22:34

Reviving this thread regarding Godot 3. The below solution works in Godot 2 but now I want to do this in Godot 3. How can I do this? If I should start a new thread, please let me know.

Anyone know how to do this in Godot 3?

davidpgil | 2018-11-11 23:10

:bust_in_silhouette: Reply From: wombatstampede

You could write a shader/create a shader material which sets the alpha value in diffuse_alpha dependent on the color value.

http://docs.godotengine.org/en/stable/learning/features/shading/shading_language.html

This one also touches the alpha topic:
http://docs.godotengine.org/en/stable/learning/features/shading/shading_language.html

Or you simply import the png texture and use the imported *.tex file if you just don’t like the png format for some reason (patents, licenses, local regulations i.d.k.)

Thanks for your reply!

I am just starting with Godot and didn’t know about shaders in Godot so I think I now have my work cut out for me with the links you provided. Though, both links (at the moment) are the same? Thankfully I am familiar with C.

I’m not aware of *.tex files so I think I need to investigate that as well. Can the tex file be used to manipulate the the format of the image? For example, can I take a high-res image and make it 8 colors and indexed, for example?

I’m experimenting with using only FOSS tools for creating my game. I wasn’t aware that PNG had any issues with free software/ patents.

Thanks for your info – Threw a lot of homework on my lap ^_^"

==== UPDATE 1
So, I created this script and its not working. I am still researching. Im about to turn in for the night (im in asia), but I thought I would post my non-working shader in case you had anything to add/say.

// specify the color to be transparent which is r255, g0, b255 or what I like to call hot pink 
color alpha_color = vec4(1.0, 0.0, 1.0, 1.0);
color texscreen sample_pixel = vec2(0, 0);

// if the pixel matches hotpink, make it transparent
if(sample_pixel == alpha_color)
{
	COLOR.a = 0.0;
}

davidpgil | 2017-10-07 22:46

First, sorry about the missing link. Obviously a Copy & Paste error.
The missing link is (i think):
https://forum.godotengine.org/13010/alpha-masking-a-3d-object-using-materialshader-language?show=13010#q13010

About patents:
PNG basically has no (known) patent problems:
PNG Frequently Asked Questions

I did just not know which reasons led you to avoid the PNG-format.
This is because PNG can as well works with a (arbitrary) limited amount of colors and either alpha-channel transparency or single-color transparency.

The *.tex advice was just a way to avoid the png-format if you (for unknown reasons on my side) want to avoid PNG because of the format itself.

My advice is still to simply use the png-format. But if you want to experiment with shaders. Here’s a material shader (fragment):

uniform texture diffuse;
color col = tex(diffuse,UV).rgba;
if (col.r==1.0 && col.g==0.0 && col.b==1.0) {
	col.a=0.0;
}
DIFFUSE_ALPHA=col;

You might have to switch other shaders off to have this working fully. I.e. switch mipmap & filter flags off for the diffuse texture.
I tested this in 3D. Might be slightly different for 2D.

wombatstampede | 2017-10-08 10:40

That worked! With a small tweak. I needed to change “DIFFUSE_ALPHA=col;” to “COLOR=col;” … Many thanks!

Thanks for the corrected link about shaders in Godot.

davidpgil | 2017-10-09 01:09

… I’m fine with PNG. it’s a great format. I am hoping there is some benefit to using indexed PNGs instead of PNGs with an alpha channel down the road, however. I am in a very early investigative/learning phase with my project. At the moment I am simply trying to replicate my workflow for when I was working on Gameboy games. Back then we used PNGs :slight_smile:

OK. You basically gave me all I need. You have my regards, sir!

davidpgil | 2017-10-09 01:10

:bust_in_silhouette: Reply From: Achenar

Per answer to Set Single Color To Transparent using shaders? - Archive - Godot Forum

I had very similar sounding reasons for not using PNG - trying to support ‘legacy’ data files that include bmp and other supporting data files that specify the transparent color for the texture etc.


I managed to achieve something along these lines through a custom spatial shader that sets ‘discard’ if the underlying texture color matches a certain value. In my situation, I am generating meshes and applying textures at runtime from legacy formats (including bmp) which have alpha color specified in some of the supporting data files.

Example shader code and (C#) script to achieve this is below - note it’s somewhat hacked together to assume that the “transparent” color is bright blue (rgb 0,0,255).

C# script to assign the shader

ImageTexture tex = new ImageTexture();
Error e = tex.Load("path/to/texture.bmp");
ShaderMaterial sm1 = new ShaderMaterial();

sm1.Shader = ResourceLoader.Load<Shader>("res://simple_trans_tex.shader");
sm1.SetShaderParam("day_texture", tex);

Shader (saved in project as simple_trans_tex.shader)

shader_type spatial; 
render_mode cull_disabled;

uniform sampler2D day_texture : hint_albedo;

void fragment() {
    vec3 day_tex_color = texture(day_texture, UV ).rgb;

	// filter out transparent color
	float blue = 255f / 255f;
	
	ALBEDO = day_tex_color;

	// discard pixels (transparency) when 8 bit blue = 255
    if (day_tex_color.r==0.0 && day_tex_color.g==0.0 && day_tex_color.b==1.0) {   
	   discard = true;
	}
}