Godot Version
4.3
Question
`So i’m attempting a cleaning system kind of like Viscera cleanup detail/power wash sim and for the most part i understand you need to utilize shaders on an object and then get the UV position of an object and then work from there. I utilized the basic framework of another users’(evoshogames at godotshaders) work doing something similar, but he utilized a raycast system and almost a 2D perspectivefor aiming/cleaning so i attempted to fix it up to fit my needs. I’m just seeing if anyone has done somthing similar and can give me pointers on where to go/if i should be using something else instead. currently my scripts are as follows:
On the dirt cube-
`extends MeshInstance3D
var mask_image: Image
var dirt_mask: ImageTexture
func _ready():
# Create a white mask (fully dirty)
mask_image = Image.new() # This should be created with the size of your dirt mask texture
#mask_image = Image.create(dirt_mask_size, dirt_mask_size, false, Image.FORMAT_L8)
mask_image.fill(Color(1, 1, 1)) # White = Full Dirt
# Create texture from the mask
dirt_mask = ImageTexture.new()
dirt_mask = ImageTexture.create_from_image(mask_image)
#sets our dirt_mask from our shader to the dirt_mask we just made
var override_material: ShaderMaterial = get_surface_override_material(0)
override_material.set_shader_parameter(‘dirt_mask’, dirt_mask)
func clean_surface(brush_position: Vector3, brush_size: int):
# Convert world position to local texture coordinates
var local_position = brush_position
mask_image.set_pixel(brush_position.x, brush_position.z, Color(0, 0, 0)) # Set to black (clean)
# Update the dirt mask texture
dirt_mask = ImageTexture.create_from_image(mask_image)
#update the shader to use the updated mask texture
var override_material: ShaderMaterial = get_surface_override_material(0)
override_material.set_shader_parameter('dirt_mask', dirt_mask)`
on the mop-
extends Area3D
func _ready():
connect("area_entered", _on_mop_hits_dirty_object)
func _on_mop_hits_dirty_object(area):
var dirty_object = area.get_parent() # Get the parent node (MeshInstance3D)
print(dirty_object)
if dirty_object is MeshInstance3D and dirty_object.has_method("clean_surface"):
var collision_point = global_position # Approximate impact position
print(collision_point)
dirty_object.clean_surface(collision_point, 3
shader-
shader_type spatial;
uniform sampler2D clean_texture;
uniform sampler2D dirty_texture;
uniform sampler2D dirt_mask;
// Control for the amount of dirtiness applied
uniform float dirt_strength : hint_range(0.0, 1.0) = 1.0;
void fragment() {
// Sample colors from the clean and dirty textures
vec4 clean_color = texture(clean_texture, UV);
vec4 dirty_color = texture(dirty_texture, UV);
// Sample the dirt mask (typically a grayscale texture)
float mask_value = texture(dirt_mask, UV).r;
// Adjust the mask by dirt_strength to control the blending
float adjusted_mask = mask_value * dirt_strength;
// Final blend factor considering both the mask and the dirty texture's alpha
float blend_factor = adjusted_mask * dirty_color.a;
// Blend the clean and dirty colors, preserving some of the clean texture's influence
vec4 final_color = mix(clean_color, dirty_color, blend_factor);
// For ALPHA, use the higher of clean or dirty alpha to ensure visibility
ALBEDO = final_color.rgb;
ALPHA = max(clean_color.a, blend_factor);
}
`
And thank you if you’ve had the patience to read all this