Quick answer: Use material.set_shader_parameter("my_tex", my_texture) at runtime, or assign in the material inspector. Declare with hints (source_color, repeat_enable, filter_linear) for correct color and sampling behavior.

Here is how to fix Godot 4 shader sampler2D uniforms that sample black, sample the wrong texture, or produce inverted colors. Texture uniforms have specific hints that affect color space and sampling; missing hints produce subtle bugs.

The Symptom

Shader uses a custom texture uniform. Output is solid black or shows the wrong texture. Inspector shows the texture assigned correctly.

What Causes This

Uniform not bound. Default sampler is a black/white fallback. Without a binding, that fallback samples.

Color space mismatch. Color textures need source_color hint for proper sRGB-linear conversion. Without it, colors look washed out or incorrect.

Wrong filter/repeat hint. Texture appears tiled when you wanted clamp, or pixelated when you wanted bilinear.

The Fix

Step 1: Declare uniforms with proper hints.

shader_type canvas_item;

uniform sampler2D tint_tex : source_color, repeat_enable, filter_linear;
uniform sampler2D mask_tex : hint_default_white, repeat_disable, filter_linear;
uniform sampler2D normal_tex : hint_normal, repeat_enable, filter_linear;

source_color for albedo; hint_normal for normal maps; hint_default_white for fallback.

Step 2: Bind from script.

extends Sprite2D

@export var palette: Texture2D

func _ready():
    material.set_shader_parameter("tint_tex", palette)

Or assign in the material inspector and skip the script call.

Step 3: Sample correctly in fragment.

void fragment() {
    vec4 tint = texture(tint_tex, UV);
    COLOR.rgb *= tint.rgb;
}

Step 4: For RenderTextures, use viewport_path.

uniform sampler2D screen_tex : hint_screen_texture;
// or
uniform sampler2D depth_tex : hint_depth_texture;

Built-in screen and depth hints provide automatic binding.

Step 5: Debug with a known color.

// Temporarily output the texture directly
void fragment() {
    COLOR = texture(tint_tex, UV);
}

If that shows the texture correctly, your math elsewhere is the issue. If still black, the binding or hint is wrong.

“source_color for color, hint_normal for normals, hint_default_white for fallback. Bind with set_shader_parameter.”

Related Issues

For shader color banding, see Color Banding in Export. For RichText effects, see RichText Effect.

Right hint for the texture type. set_shader_parameter at runtime. Samples come through correctly.