-
-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Instancing using instanced vertex attributes #324
Comments
I'm definitely on board with the idea of adding something like this, as Tetra's instancing support is fairly limited at the moment. I'm not sure if https://love2d.org/wiki/love.graphics.drawInstanced#Examples Looking at that, I think there's two missing pieces here:
So that might be the best way to break the problem down. This does seem like it has potential to be a large change, so I should warn in advance that I don't know when I'll have the time/energy to review it, but feel free to give it a go if you'd still find it interesting! |
I have already conceptualized another API proposal. It addresses some of the problems you mentioned. I will go into further detail further down below. I'd argue that
One downside is the inconvenience arising for the user, who then has to manually switch data for the buffers (or the buffers themselves) when he wants to draw multiple instanced meshes with the same shader. The new API would look as follows: fn new(ctx: &mut Context) -> tetra::Result<GameState> {
// Create the buffer with an initial capacity of 10,000 Vec2 and optimization for streamed drawing
let offset_buffer: AttributeBuffer<Vec2<f32>> =
AttributeBuffer::new(ctx, Vec::<Vec2<f32>>::with_capacity(10_000), BufferUsage::Stream);
// Load the shader program
let shader = Shader::from_vertex_file(ctx, "path/to/vertex/shader.vert")?;
// Bind the buffer to an attribute defined in the shader program
shader.set_vertex_attribute(ctx, "a_offsets", offset_buffer, Divisor::Instance(1));
graphics::set_shader(ctx, &shader);
// Optionally, the offset_buffer can be stored in the state for later modification during the game loop
// This would not be necessary if we created a static buffer which is only bound during initialization
Ok(GameState{
offset_buffer
}
}
// ...
fn draw(&mut self, ctx: &mut Context) -> tetra::Result {
let mut offsets = Vec::new();
// Push offsets here
// Set data of offset_buffer
self.offset_buffer.set_data(ctx, offsets);
// Draw an instanced mesh, which is being processed by the currently active shader
some_mesh.draw_instanced(ctx, offsets.len(), DrawParams::default());
} The buffer creation: let offset_buffer: AttributeBuffer<Vec2<f32>> =
AttributeBuffer::new(ctx, Vec::<Vec2<f32>>::with_capacity(10_000), BufferUsage::Stream); can be done using the three types of usage: The shader.set_vertex_attribute(ctx, "a_offsets", offset_buffer, Divisor::Instance(1)); could be replaced with Lastly setting the data in this line: self.offset_buffer.set_data(ctx, offsets); would automatically grow the buffer size if the |
As I just got assigned a new project in school while barely having much free time at all I don't expect to be capable of working on this in the next upcoming semester :( |
Summary
I want to implement a non-breaking method for instanced draw calls without the size limit of uniform arrays. For this, I'd like to use instanced arrays as vertex attributes.
The proposed API would look as follows:
It is very similar to the current uniform approach. Therefore offsets in this concrete example requires at least 10000 entries.
I am opening an issue for this, as I'd like to inform you about my intentions beforehand and because you may have some feedback or concerns regarding the API design or even overall idea.
Sidenote: As I am very new to OpenGL and barely having much freetime due to school, side job and my diploma thesis, this contribution may well take some time till it is complete.
Motivation/Examples
I'd need this change for a game prototype I am writing. I need to draw the same object 100s of 1000s of times. This leaves quite a performance impact. Instancing would be the ideal solution, but tetra currently only supports instancing using uniform arrays, which have quite a significant size limitation, only allowing some 1000s instances. Using instanced arrays, this limit can practically be (almost) completely removed, allowing even more performance gain due to even less draw calls.
One concrete use case would be very heavy particle effects, where half a million equal particles need to be drawn at the same time. Or for really suffisticated cellular automata simulations, where cellular states are better not to be stored as color in a texture but a more complex object.
Alternatives Considered
Two alternative API designs I've considered are the following:
But I think this is too long and stateful.
This is concise and effective, but in my humble opinion the originally proposed design better integrates into the current "workflow" for instancing.
The text was updated successfully, but these errors were encountered: