0 votes

Ok, so i have a scenario where one node is responsible for rendering a lot of other nodes (2DColliders) using a specific material shader.

The shader has an Uniform which store the object color (a Vec4), and while iterating through all the 2DColliders i need to render, every time i just set the uniform to the object Modulate:

func _draw():
#
    for m in meta_group.get_children():

    var sz = Vector2(m.get_node("CollisionShape2D").shape.radius * 2, m.get_node("CollisionShape2D").shape.radius * 2)
    get_material().set_shader_param("modulate", m.modulate)
    draw_set_transform(m.position, 0, Vector2(1, 1))
    draw_texture_rect(texture, Rect2(-sz.x, -sz.y, sz.x*2, sz.y*2), false, modulate)

But when playing the game, instead of each node has its specific color, all of them are rendered with only one color (which i assume is the last modulate iterated)

This is the code that spawns the 2D Colliders to be rendered:

func spawn_paint():
var m = meta.instance()
m.position = get_node("Brush/Node2D").get_global_transform().get_origin()

var vel = (get_node("Brush/Node2D").get_global_transform().get_origin() - get_node("Brush").get_global_transform().get_origin()).normalized()
m.linear_velocity = vel * 300
m.modulate = Color().from_hsv(colorTimer - int(colorTimer), 1, 1, 1)
m.linear_velocity = m.linear_velocity.rotated(rand_range(-0.1, 0.1))
m.get_node("CollisionShape2D").set_shape(CircleShape2D.new())
m.get_node("CollisionShape2D").shape.radius = rand_range(3,6)

get_tree().get_root().get_node("Root/MetaGroup").add_child(m)

I use a timer to shift a HUE value to make the colliders interpolate to al HUE values.

But when i run the game, this is what is rendered: (when i shoot a ball, ALL the balls are set with the same color)

Result

Is there any rendering 2D Pipeline that could be doing this behaviour?

What i have imagined is that probably, when i call "drawtexturerect", it doesnt draw imediately, and insteady adds to a "batcher", and at the end of the "_draw()" function, it then renders all of them at once using only the last shader param setted.

If this is the case, is there any way to "force" a batch flush so it can be rendered each one with an specific uniform value?

asked Apr 13, 2019 in Engine by RotcivOcnarb (15 points)

Seems to be that all material uses the same material instance. So the shader uniform is shared by all material(s).

Try to assign an individual copy of the material to each instance of your texturerect (or whatever you use it in.) You can use the method ".duplicate()" to make a copy of any resource (including shader materials).

I hope it works.

Thanks for the help, but i don't think that is the case.

The thing is that the 2DColliders do not have a Material object, the modulate property is a separeted property from the material, within te CanvasItem object:

enter image description here
I do have made a test by assigning a different Material instance to each Collider, but that didn't make any effect

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.