I am interested in using the drawInstanced() function, but I am struggling to understand how to update the positions of each instance of a mesh. The example here: https://love2d.org/wiki/love.graphics.drawInstanced shows the positions of the triangles being sent to the shader one time.
Using the example on the wiki page:
Obviously if I want to update the position, I need to pass the new positions of the vertices to the shader every frame. But I don't know how to do that. shader:send() doesn't help because that only sends uniforms. I figure maybe I need to use setVertexAttribute() every frame, but when I try that nothing renders.
I also tried simply looping through the table of positions ("instancepositions") and setting pos.x,and pos.y, thinking that maybe since that attribute is already attached, then all I would need to do is update the values in the table. But that also does nothing. in fact, if I print out pos.x and pos.y, I just get 0,0, and that seems to be the only value in the instancepositions table, even though print(#instancepositions") has 2,304 values in it.
So I am just lost. I need each instance of a mesh to have its own position and movement, and I don't know how to do that in combination with drawInstanced().
I appreciate any help!
How do I update the positions of instances of meshes?
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: How do I update the positions of instances of meshes?
You don't send the positions to the shader directly, you update them by calling instancemesh:setVertexAttribute with the instance number, the attribute index, and the position values.
Re: How do I update the positions of instances of meshes?
Ah, I see. I was close then, I was just trying to update the wrong mesh.
I got it working with this basic proof of concept:
Is the instancemesh required when using drawInstanced? Or can I simply operate on the regular mesh directly? Is that wise when instancing?
I got it working with this basic proof of concept:
Code: Select all
local testx = 0
function love.update(dt)
testx = testx + 10 * dt
for i=1,instancemesh:getVertexCount() do
instancemesh:setVertexAttribute(i,1,testx,100)
end
instancemesh:setVertexAttribute(2,1,testx,400)
end
Re: How do I update the positions of instances of meshes?
It's not required IIRC. If you don't have an attribute mesh then you can't change the attributes of the instances, and you have to use uniforms instead, which kind of defeats the purpose of instancing.
Re: How do I update the positions of instances of meshes?
So, in this example, self.dir is randomly either 1 or -1. This is just to try to get the circles to move in different directions for testing.
My draw code is like this:
Here is how everything gets setup (the for loop here seems wrong):
My circles still move all together, on top of each other, despite the movement code theoretically moving them at different speeds and directions.
What am I missing here?
Is it that I am only inserting to the instancepositions table one time, at load? Or something?
Code: Select all
for c,self in ipairs(circles) do
self.x = self.x + (self.speed * dt)* self.dir--just testing
self.y = self.y + (self.speed * dt) * self.dir--just testing
for i=1,instancemesh:getVertexCount() do
instancemesh:setVertexAttribute(i,1,self.x,self.y)
end
end
Code: Select all
lg.setShader(shader)
lg.drawInstanced(mesh, #instancepositions,0,0,0,instanceScale,instanceScale)
lg.setShader()
Here is how everything gets setup (the for loop here seems wrong):
Code: Select all
function Circle:load()
for i=1,instanceCount do
local pos = {400/instanceScale,400/instanceScale,random(1,10)}
self:create(400/instanceScale,400/instanceScale,random(1,10))
table.insert(instancepositions,pos)
end
instancemesh = love.graphics.newMesh({{"InstancePosition", "float", 2}}, instancepositions, nil, "static")
mesh:attachAttribute("InstancePosition", instancemesh, "perinstance")
end
What am I missing here?
Is it that I am only inserting to the instancepositions table one time, at load? Or something?
- slime
- Solid Snayke
- Posts: 3166
- Joined: Mon Aug 23, 2010 6:45 am
- Location: Nova Scotia, Canada
- Contact:
Re: How do I update the positions of instances of meshes?
Your circle update code is overwriting every instance position with the same value in each iteration of the loop over the circles array - so only the position of the last element of that array is being applied, and it's applying to every instance instead of a specific one.
Re: How do I update the positions of instances of meshes?
Thanks for that helpful hint!
I don't know if this is correct or not, but I found that it works when I replace i with c:
I don't know if this is correct or not, but I found that it works when I replace i with c:
Code: Select all
for c,self in ipairs(circles) do
print(self.dir)
self.x = self.x + (self.speed * dt)* self.dir--just testing
self.y = self.y + (self.speed * dt) * self.dir--just testing
for i=1,instancemesh:getVertexCount() do
instancemesh:setVertexAttribute(c,1,self.x,self.y)
end
- slime
- Solid Snayke
- Posts: 3166
- Joined: Mon Aug 23, 2010 6:45 am
- Location: Nova Scotia, Canada
- Contact:
Re: How do I update the positions of instances of meshes?
In that case you can get rid of the inner for-loop entirely, as long as instancemesh has at least as many elements in it as there are circles:
Code: Select all
for c,self in ipairs(circles) do
self.x = self.x + (self.speed * dt) * self.dir--just testing
self.y = self.y + (self.speed * dt) * self.dir--just testing
instancemesh:setVertexAttribute(c,1,self.x,self.y)
end
Re: How do I update the positions of instances of meshes?
Yeah, that makes sense. Thank you! I'm a novice with instancing of meshes, so this is super helpful.
Who is online
Users browsing this forum: No registered users and 7 guests