Just to clarify, how would you do a copy of the material in code ?
Get surface material then instantiate it and apply it to the mesh ?
Just to clarify, how would you do a copy of the material in code ?
Get surface material then instantiate it and apply it to the mesh ?
Having issues here aswell. The idea for my needs is i need to add highlight when i mouse over.
I got methods to detect mouse_over over an object (collider) then i get its mesh and then do stuff to the mesh.
THe problem im facing i dont understand why this not working.
func highlight_object(collider, is_mouse_entered:bool):
if collider is Item:
var mesh = collider.item_mesh
var material_count = mesh.get_surface_override_material_count()
for i in range(material_count):
var mat = mesh.get_active_material(i)
if is_mouse_entered:
var new_mat = mat.duplicate()
new_mat.next_pass = HIGH_LIGHT
mesh.set_surface_override_material(i,new_mat)
else:
mat.next_pass = null
I got two types of items
Hat
Potion
In the world i have these two scenes and duplicated them in the world tree.
As you can see in the video the potion item works fine, i can highlight each of the items separately but the hats are wierd. One highlights the other.
EDIT:
I just realized that i CTRL + D in the world tree to duplicate the Hat scene, and thats why.
Even if i set to local:
func highlight_object(collider, is_mouse_entered:bool):
if collider is Item:
var mesh = collider.item_mesh
var material_count = mesh.get_surface_override_material_count()
for i in range(material_count):
var mat = mesh.get_active_material(i)
if is_mouse_entered:
var new_mat:Material = mat.duplicate()
new_mat.next_pass = HIGH_LIGHT
new_mat.resource_local_to_scene = true
mesh.set_surface_override_material(i,new_mat)
else:
mat.next_pass = null
Same result.
Also tried to check the
Not helping
But that is exactly what im doing here:
func highlight_object(collider, is_mouse_entered:bool): if collider is Item: var mesh = collider.item_mesh # < --------- This is MeshInstance3D node var material_count = mesh.get_surface_override_material_count() for i in range(material_count): var mat = mesh.get_active_material(i) if is_mouse_entered: var new_mat:Material = mat.duplicate() new_mat.next_pass = HIGH_LIGHT new_mat.resource_local_to_scene = true mesh.set_surface_override_material(i,new_mat) else: mat.next_pass = null
Im not going into the mesh resource, only meshinstance to get material count and loop through all materials and set the next pass.
I tried to set the first material before i made the loop, and it didnt work for some reason, thats why i made the loop, and the material duplicate thing.
Will have to debug it later.. it makes no sense.
xyz Some meshes have multiple materials hence the loop but i set it like this real quick
func highlight_object(collider, is_mouse_entered:bool):
if collider is Item:
var mesh = collider.item_mesh
var material_count = mesh.get_surface_override_material_count()
for i in range(material_count):
var mat = mesh.get_active_material(i)
if is_mouse_entered:
var new_mat:Material = mat.duplicate()
new_mat.next_pass = HIGH_LIGHT
new_mat.resource_local_to_scene = true
mesh.material_override=new_mat #< --------------------------------------------
#mesh.set_surface_override_material(i,new_mat)
else:
mat.next_pass = null
pass
Result the same
xyz
Did more tests, it seems something is broken.
As per some tutorial i generated "outline" mesh for the mesh, set the highlight material and set visibility to false.
And i get the same behavior with setting the mesh visibility that i get setting materials.
if i hover on one the other one lights up but not the one i hover on.
func highlight_object(collider, is_mouse_entered:bool):
if collider is Item:
var mesh = collider.item_mesh
print("mesh : - ",mesh)
var outline_mesh = mesh.get_child(0)
if is_mouse_entered:
outline_mesh.visible = true
else:
outline_mesh.visible = false
Printouts:
entered player mouse
mesh : - flask:<MeshInstance3D#47513077244>
exited player mouse
mesh : - flask:<MeshInstance3D#47513077244>
exited player mouse
mesh : - flask:<MeshInstance3D#47513077244>
entered player mouse
mesh : - flask:<MeshInstance3D#47513077244>
The thing fired twice, not sure why but i hovered on 2 different potions, seems like they are the same instance..
Yes i have duplicated them with CTRL + D and moved in the world tree.
But i dont see how can i make it unique
kuligs2 The problem is likely in what (and when) is assigned to your item_mesh
property since it apparently has the same value for all instances. If you're assigning in editor via exported reference you should instead assign upon instantiation in _ready()
. Hard to debug from screenshots though, I'm guessing here. Make a minimal reproduction project and post it so we can take a look.
kuligs2 You can instance manually, just reassign the references in code at startup or try not duplicating instances via ctrl D, but instead drag each new instance to the scene from the file system window. This is a known pitfall and can be worked around in various ways depending on your project's setup and preferred workflow. Tbh I thought someone already complained about it at Godot's github. This was also discussed at length here before, so search around.
xyz but as you say, dragging from file browser on the scene tree works as it should. Materials/meshes are setting when i hover on with mouse and printouts give me different instance ID's. Wish ctrl + D did the same, instead of dragging with mouse. Maybe they could implement CTRL + Shift +D makes duplicate of the same instance and CTRL + D makes a new instance
kuligs2 don't change material, use a custom shader with instance uniform.
if you are using a standard material, you can click on it and do convert to shader
.
In your shader, set the things that need to change, in this case the amount of vertex displacement and maybe color and alpha, to an instance uniform:
instance uniform vec3 albedo : source_color;
instance uniform float grow = 0.0
you can make the effect disappear by either setting the displacement very low, or using scissor transparency and setting the scissor
or alpha
to 0.
this will add a new tab in geometry where you can change the instance uniforms. these are unique to each object, so if you change one, the others will not be affected. It also has the best performance.
finally, in your script you can change the uniform instances of the meshInstance3D
directly, and it will affect all materials with this uniform instance name in your mesh:
$metarig/Skeleton3D/Hair.set_instance_shader_parameter("albedo", Color.BLACK)
Jesusemora this does not work.
Code that sets stuff on mouse over:
if collider is Item:
var mesh :MeshInstance3D = collider.item_mesh
var material_count = mesh.get_surface_override_material_count()
if is_mouse_entered:
print(mesh)
mesh.set_instance_shader_parameter("uniform",1.0)
mesh.set_instance_shader_parameter("grow",0.05)
mesh.set_instance_shader_parameter("albedo",Color.CHARTREUSE)
else:
mesh.set_instance_shader_parameter("uniform",0.0)
mesh.set_instance_shader_parameter("grow",0.0)
mesh.set_instance_shader_parameter("albedo",Color.BLACK)
shader code:
// NOTE: Shader automatically converted from Godot Engine 4.2.1.stable's StandardMaterial3D.
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;
uniform float point_size : hint_range(0,128);
uniform float roughness : hint_range(0,1);
uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_enable;
uniform float specular;
uniform float metallic;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
uniform vec3 uv2_scale;
uniform vec3 uv2_offset;
instance uniform float grow = 0.0;
void vertex() {
UV=UV*uv1_scale.xy+uv1_offset.xy;
}
void fragment() {
vec2 base_uv = UV;
vec4 albedo_tex = texture(texture_albedo,base_uv);
ALBEDO = albedo.rgb * albedo_tex.rgb;
float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);
METALLIC = metallic_tex * metallic;
vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);
float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);
ROUGHNESS = roughness_tex * roughness;
SPECULAR = specular;
}
kuligs2 this does not work
You skipped a step
Jesusemora In your shader, set the things that need to change, in this case the amount of vertex displacement and maybe color and alpha, to an instance uniform:
instance uniform vec3 albedo : source_color;
instance uniform float grow = 0.0
Jesusemora
you mean albedo in shader?
it was already defined so i removed it otherwise it errors out
kuligs2 // NOTE: Shader automatically converted from Godot Engine 4.2.1.stable's StandardMaterial3D.
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx;
uniform vec4 albedo : source_color; <-----------------------------------------------------------------------------
uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;
uniform float point_size : hint_range(0,128);
uniform float roughness : hint_range(0,1);
uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_enable;
uniform float specular;
uniform float metallic;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
uniform vec3 uv2_scale;
uniform vec3 uv2_offset;