Skip to content

Commit 98b8bf6

Browse files
committed
Support instanced rendering
1 parent c1c47e4 commit 98b8bf6

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

demosys/opengl/vao.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,20 @@ class VAOError(Exception):
2626

2727
class BufferInfo:
2828
"""Container for a vbo with additional information"""
29-
def __init__(self, buffer: mgl.Buffer, buffer_format: str, attributes=None):
29+
def __init__(self, buffer: mgl.Buffer, buffer_format: str, attributes=None, per_instance=False):
3030
"""
3131
:param buffer: The vbo object
3232
:param format: The format of the buffer
3333
"""
3434
self.buffer = buffer
3535
self.attrib_formats = types.parse_attribute_formats(buffer_format)
3636
self.attributes = attributes
37+
self.per_instance = per_instance
3738

3839
# Sanity check byte size
3940
if self.buffer.size % self.vertex_size != 0:
40-
raise VAOError("Buffer with type {} has size not aligning with {}. Remainder: ".format(
41-
buffer_format, self.vertex_size, self.buffer.size % self.vertex_size,
41+
raise VAOError("Buffer with type {} has size not aligning with {}. Remainder: {}".format(
42+
buffer_format, self.vertex_size, self.buffer.size % self.vertex_size
4243
))
4344

4445
self.vertices = self.buffer.size // self.vertex_size
@@ -61,12 +62,12 @@ def content(self, attributes: List[str]):
6162

6263
attributes.remove(attrib)
6364

64-
if len(attrs) == 0:
65+
if not attrs:
6566
return None
6667

6768
return (
6869
self.buffer,
69-
" ".join(formats),
70+
"{}{}".format(" ".join(formats), '/i' if self.per_instance else ''),
7071
*attrs
7172
)
7273

@@ -98,21 +99,24 @@ def __init__(self, name, mode=mgl.TRIANGLES):
9899
self.vertex_count = 0
99100
self.vaos = {}
100101

101-
def draw(self, shader: ShaderProgram, mode=None):
102+
def draw(self, shader: ShaderProgram, mode=None, vertices=-1, first=0, instances=1):
102103
"""
103104
Draw the VAO.
104105
Will use ``glDrawElements`` if an element buffer is present
105106
and ``glDrawArrays`` if no element array is present.
106107
107108
:param shader: The shader to draw with
108109
:param mode: Override the draw mode (GL_TRIANGLES etc)
110+
:param vertices: The number of vertices to transform
111+
:param first: The index of the first vertex to start with
112+
:param instances: The number of instances
109113
"""
110114
vao = self._create_vao_instance(shader)
111115

112116
if mode is None:
113117
mode = self.mode
114118

115-
vao.render(mode)
119+
vao.render(mode, vertices=vertices, first=first, instances=instances)
116120

117121
def transform(self, shader, buffer: mgl.Buffer, mode=None, vertices=-1, first=0, instances=1):
118122
"""
@@ -132,14 +136,18 @@ def transform(self, shader, buffer: mgl.Buffer, mode=None, vertices=-1, first=0,
132136

133137
vao.transform(buffer, mode=mode, vertices=vertices, first=first, instances=instances)
134138

135-
def buffer(self, buffer, buffer_format: str, attribute_names):
139+
def buffer(self, buffer, buffer_format: str, attribute_names, per_instance=False):
136140
"""
137141
Register a buffer/vbo for the VAO. This can be called multiple times.
138142
adding multiple buffers (interleaved or not)
139143
140144
:param buffer: The buffer object. Can be ndarray or Buffer
141145
:param buffer_format: The format of the buffer ('f', 'u', 'i')
146+
:returns: The buffer object
142147
"""
148+
if not isinstance(attribute_names, list):
149+
attribute_names = [attribute_names, ]
150+
143151
if not isinstance(buffer, mgl.Buffer) and not isinstance(buffer, numpy.ndarray):
144152
raise VAOError("buffer parameter must be a moderngl.Buffer or numpy.ndarray instance")
145153

@@ -150,9 +158,11 @@ def buffer(self, buffer, buffer_format: str, attribute_names):
150158
if len(formats) != len(attribute_names):
151159
raise VAOError("Format '{}' does not describe attributes {}".format(buffer_format, attribute_names))
152160

153-
self.buffers.append(BufferInfo(buffer, buffer_format, attribute_names))
161+
self.buffers.append(BufferInfo(buffer, buffer_format, attribute_names, per_instance=per_instance))
154162
self.vertex_count = self.buffers[-1].vertices
155163

164+
return buffer
165+
156166
def index_buffer(self, buffer, index_element_size=4):
157167
"""
158168
Set the index buffer for this VAO
@@ -198,7 +208,7 @@ def _create_vao_instance(self, shader):
198208
vao_content.append(content)
199209

200210
if len(attributes) > 0:
201-
raise VAOError("Did not find a buffer mapping for {}".format([n.name for n in attributes]))
211+
raise VAOError("Did not find a buffer mapping for {}".format([n for n in attributes]))
202212

203213
if self._index_buffer:
204214
vao = context.ctx().vertex_array(shader.program, vao_content,

0 commit comments

Comments
 (0)