Decal Shader for 4.3 compatibility renderer + transparency support & no repeat

Based on this code but adjusted for this change.
I also added transparency support and turned off repeat on the texture.

HOW TO USE:
1. Plug your pic into “texture albedo”
2. the texture must have square aspect ratio.
3. do not have pixels touching the edges or it will result in the defect like in the pictures.

WARNING:
Godot 4.3 has some weird bug where if the decal is showing for the first 2 frames of the scene, it renders completely black.

I fixed this by showing it few frames later.

Shader code
shader_type spatial;
render_mode world_vertex_coords, unshaded;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : hint_default_white, repeat_disable;
uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap;

uniform float scale_mod = 1.0;
uniform float cube_half_size = .5;

varying mat4 INV_MODEL_MATRIX;

void vertex(){
	INV_MODEL_MATRIX = inverse(MODEL_MATRIX);
}

// Credit: https://stackoverflow.com/questions/32227283/getting-world-position-from-depth-buffer-value
vec3 world_pos_from_depth(float depth, vec2 screen_uv, mat4 inverse_proj, mat4 inverse_view) {
	float z = depth * 2.0 - 1.0;
	vec4 clipSpacePosition = vec4(screen_uv * 2.0 - 1.0, z, 1.0);
	vec4 viewSpacePosition = inverse_proj * clipSpacePosition;
	viewSpacePosition /= viewSpacePosition.w;
	vec4 worldSpacePosition = inverse_view * viewSpacePosition;
	return worldSpacePosition.xyz;
}

void fragment() {
	float depth = texture(DEPTH_TEXTURE, SCREEN_UV).x;
	vec3 world_pos = world_pos_from_depth(depth, SCREEN_UV, INV_PROJECTION_MATRIX, (INV_VIEW_MATRIX));
	vec4 test_pos = (INV_MODEL_MATRIX * vec4(world_pos, 1.0));
	
	if (abs(test_pos.x) > cube_half_size ||abs(test_pos.y) > cube_half_size || abs(test_pos.z) > cube_half_size) {
		discard;
	}
	
	
	
	ALBEDO = texture(texture_albedo, (-test_pos.xz * scale_mod) + 0.5).rgb * albedo.rgb;
	ALPHA = texture(texture_albedo, (-test_pos.xz * scale_mod) + 0.5).a * albedo.a;
}
Tags
decal
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Sketchy renderer with optional shadow and tinting.

Dither opacity with GLES2 Support

Decal shader 4.0 port

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
ioltnas
ioltnas
1 month ago

Changing the if conditions to

if (abs(test_pos.x) * scale_mod > cube_half_size || abs(test_pos.y) * scale_mod > cube_half_size || abs(test_pos.z) * scale_mod > cube_half_size) {
makes it so pixels can touch the edge.

Last edited 1 month ago by ioltnas