I am trying to set a Sampler2D parameter on a mesh/material created using the RenderingServer function but setting the Sampler2D parameter doesn’t seem to work or do anything even though using the exact same resource with the regular set_shader_parameter function on a normal mesh works just fine and setting the parameter to a String does actually set the parameter (I can print it out and see) but it doesn’t do anything. I tried setting it to a Resource like the normal set_shader_parameter and it just sets it as null every time even though the exact same resource works with the set_shader_parameter, even if make sure to keep the resource reference stored it makes no difference
I see nothing on this stuff online anywhere and the API docs for the material_set_param function is a whopping 4 words long so im pretty lost, hoping someone here can help
extends Node3D
var sphere_instances: Array[RID]
@onready var sphere_mesh : RID = RenderingServer.make_sphere_mesh(64, 32, 0.5)
func _ready() -> void:
create_mesh(0)
create_mesh(2)
func create_mesh(origin : int) -> void:
# Create and store mesh instance
var sphere_instance : RID = RenderingServer.instance_create()
sphere_instances.append(sphere_instance)
# Create shader materials
var material : RID = RenderingServer.material_create()
var body_shader : RID = RenderingServer.shader_create()
var body_code : String = FileAccess.get_file_as_string("res://gfx/shaders/stellar_body.gdshader")
RenderingServer.shader_set_code(body_shader, body_code)
RenderingServer.material_set_shader(material, body_shader)
var resource : Resource = preload("res://gfx/Terrestrial/Terrestrial5.dds")
# Setting Sampler2D on a normal mesh material works fine.
$MeshInstance3D.get_active_material(0).set_shader_parameter("albedo_texture", resource)
# Setting a parameter that is not a Sampler2D works fine.
RenderingServer.material_set_param(material, "albedo_mod", 2.0)
print(RenderingServer.material_get_param(material, "albedo_mod"))
# Trying to Sampler2D param on a material created with RenderingServer.material_create() does not work...
# Have tried all the ways I can think of none of them do anything.
# The second 2 here actually set the parameter but do not work in the shader.
RenderingServer.material_set_param(material, "albedo_texture", resource)
#RenderingServer.material_set_param(material, "albedo_texture", "res://gfx/Terrestrial/Terrestrial5.dds")
#RenderingServer.material_set_param(material, "albedo_texture", "gfx/Terrestrial/Terrestrial5.dds")
print(RenderingServer.material_get_param(material, "albedo_texture"))
RenderingServer.mesh_surface_set_material(sphere_mesh, 0, material)
# Set base, scenario, and transform on RID
RenderingServer.instance_set_base(sphere_instance, sphere_mesh)
RenderingServer.instance_set_scenario(sphere_instance, get_world_3d().scenario)
RenderingServer.instance_set_transform(
sphere_instance, Transform3D(Basis.IDENTITY, Vector3(origin,0,0))
)
If you can’t use a Resouce or a String and only Variant types can be passed in (according to the API docs for RenderingServer.material_set_param) what is the intended way to do this?
No I never found a way around this, I ended up having to stick with the MeshInstance3D because not having texture samplers makes it pretty much unusable What did you try? Might be a good idea to make an issue on github since it’s not just me having the problem.
As explained in the comment of the github issue RenderingServer works with RID’s so this is not a bug, you should pass the texture RID instead (using get_rid()), i opened a pr to also make this method accept the texture directly but is not sure if that will be merged.
Well I thought that was what I was doing… RenderSceneBuffersRD.CreateTexture() returns an RID, and that’s what I was trying to use. Even tried passing it through Texture2Drd but that doesn’t seem to work either.
I was trying what I found here, but it isn’t working in my case. The only real difference I can see so far between that code and mine is that code seems to be using a mesh instance and material like you would create in the editor, whereas mine is using only rendering server code directly (i.e. no nodes, nothing created in the editor). But I’m not sure if that is even relevant…
Yeah I still have no idea how to do this haha the github comments don’t make it any more clear…how do I even get an RID from a texture? I see the RenderSceneBuffersRD.create_texture() function seems to be the way to do it but I have no idea how to use this, it has like 50 parameters and not much documentation . In my example above how would I get a RID from my “res://gfx/Terrestrial/Terrestrial5.dds” texture? I see a couple examples of create_texture in godot source but none of them make much sense to me. The DataFormat and TextureUsageBits are what I really don’t get, how do I go about figuring out what these would be for my textures?
@dementive So, DataFormat is related to what sort of data you need to store in the texture. Like, if you only needed to store a single value (like a depth value), you could just use something like R32Sfloat where only the red channel is stored. But for most cases you’ll probably be fine to stick to something like R16G16B16A16Sfloat(that is a 16 bit float value in each of the R, G, B, and A channels).
The TextureUsageBits describes all the ways the texture might need to be used. I think it is mostly so it can be optimized on the gpu side. I think in most cases it should be fine to stick to SamplingBit + StorageBit.
I did figure out my issue though. This code made it work: