How do I make particles draw behind other objects based on Z position?


#1

I need to place a particle effect behind a few objects and in front of others. Changing the Z component of the position doesn’t seem to have any effect at all.


#2

Particles are rendered like that by default, but you can change that easily. Particles use a material with the tag “particle”, then the render script sets up a predicate with that tag:

function init(self)
    ...
    self.particle_pred = render.predicate({"particle"})
    ...
end

They are then drawn in a separate pass:

update(self)
    ...
    render.draw(self.particle_pred)
    ...
end

You need to make everything that should be sorted together part of the same render.draw() call. Try, for instance to add the “particles” tag to the same render predicate as the tag for the material the other objects that you want to draw have.


#3

I’ve tried above solution by doing following:

function init(self)
    ...
    self.tile_pred = render.predicate({"tile", "particle"})
    ...
end

rendering:

update(self)
    ...
    render.draw(self.tile_pred)
    -- render.draw(self.particle_pred)
    ...
end

but it did’t worked - I had only GUI rendered.
I think render.draw requires all the objects with matching tags in predicate list have the same material assigned which is not the case for sprites and particles. @sicher - could you confirm that?

I’ve fixed it by introducing new material called above_particles which is essentially a copy of sprite.material with above_particles tag instead of tiles and assigned it to all the sprites which should be drawn above particles.
I also modified render script:
init:

function init(self)
    ...
    self.tile_pred = render.predicate({"tile"})
    self.particle_pred = render.predicate({"particle"})
    self.above_particles_pred = render.predicate({"above_particles"})
    ...
end

and the rendering:

update(self)
    ...
    render.draw(self.tile_pred)
    render.draw(self.particle_pred)
    render.draw(self.above_particles_pred)
    ...
end