Transparent and emissive colors on textures

Godot Version

4.2.1

Question

Would it be possible to create a shader that would flag certain colors in a 3d texture as transparent or emissive without the need for creating masks or emission maps?

Example:

I would think so. It’s a matter of testing each colour for your criteria and then replacing the output with the thing you desire.

1 Like

Could you possibly provide an example? My coding abilities are a bit limited to say the least.

Did a thing for you.
Screeny:

And link:

Hope it’s easy to understand. I am no shader-brain!

Interesting, but I thought Godot got rid of visual scripting?

Visual Scripting and Visual Shaders are separate things, Visual Shaders are still supported

That’s good to know.

Okay, so after some research, I found that what I actually want is to have specific colors in a texture be “unshaded”, is this possible?

Don’t know exactly, but there is a Light shader too. You may get lucky.

“unshaded” applies to the entire shader, rather than just individual parts, however you could have a second pass material that is unshaded and essentially draws only certain parts of the model and skips the rest, so you can see the other material underneath.

This is probably unnecessary though, as simply having a black albido color and using the color as the emission value will achieve the same effect as unshaded and has the addiitonal benefit of interacting with dynamic lighting effects if it’s inteded to represent glowing eyes or such.

Here’s an example of using emission, I’m testing UV values to make a checkerboard pattern but you can do whatever check you want, like texting for certain texture coordinates for example, if your texture is a palette of colors.

shader_type spatial;

void fragment() {
	bool h = mod(UV.x, .3) < .15;
	bool v = mod(UV.y, .3) < .15;
	if ((h && v) || (!h && !v)) {
		ALBEDO = vec3(0.);
		EMISSION = vec3(1., .05, .09);
	}
}

It looks like this

(The dark part is because of a shadow from this spinny thing, not part of the shader)

The point is to create create a shader that mimics the fullbright colors used in the original quake, i.e. colors in a palette that are not affected by shadows.

That is what this does, I used a hardcoded color because I didn’t have a texture but you can just do EMISSION = texture(the_texture, UV) to read it from a texture.

Sorry, I didn’t realize at first.

What identifier do I put in place of “the_texture” in order to use a desired image? (My coding skills are limited to say the least :upside_down_face:)

In the shader you need to take in a texture uniform so you can read it, near the top of the shader you have

uniform sampler2D texture_name : source_color, filter_linear_mipmap, repeat_enable;

the stuff after the : is the texture hints, you can read what they do here

then you can sample the texture using UV coordinates like texture(texture_name, UV)
or by pixels if you need, like texelFetch(texture_name, pixel_coordinate, 0) (here the 0 is just the mipmap level)

When you have a sampler defined in the shader you can assign a texture to it in the inspector in godot. If you open the shader resource it’s under the “Shader Parameters” category.

This is how putting a texture into the albedo texture works for the StandardMaterial3D

Like this?

shader_type spatial;

uniform sampler2D texture_name : source_color, filter_nearest, repeat_enable;

void fragment() {
	bool h = mod(UV.x, .3) < .15;
	bool v = mod(UV.y, .3) < .15;
	if ((h && v) || (!h && !v)) {
		ALBEDO = vec3(0.);
		EMISSION;  texture(texture_name, UV);
	}
}

almost, do EMISSION = texture(...); not EMISSION; texture(...);.

Now, if you want it to apply to certain exact colors you’ll need to be able to write shader code to take the color from your texture and compare it to each of those exact colors individually, maybe by having the colors in a flat list like you showed and passing that as an additional texture. That could get pretty annoying and fiddley though.

A much easier way to go is to take the albedo texture for your model, color everything black except where the glowing colors are, color those white. Pass the black and white texture into the shader as uniform sampler2D mask_texture;
then your if can just check that to know if it needs to glow: if (texture(mask_texture, UV) > 0.5) {
and don’t forget to use the normal albedo when you’re not glowing, so before the if: ALBEDO = texture(texture_name, UV);

If you need any other help just look at the various tutorials around for how to code shaders, or read the godot manual pages about them.

Okay, but Godot insists that I not use “=” for some weird reason.
image

Also, Suppose I did want to use color comparison, is there anywhere I can research how to accomplish that sort of thing?

Oh that’s because EMISSION is a vec3, it doesn’t have an alpha value but the texture read returns all 4 channels as a vec4, you just need to do EMISSION = texture(texture_name, UV).rgb see “swizzling” in the shader docs

1 Like