Skip to content

Commit 7cde3bc

Browse files
authored
Uniforms: Support buffer protocol (#2463)
1 parent c8b6687 commit 7cde3bc

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

arcade/gl/uniform.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import struct
34
from ctypes import POINTER, cast
45

56
from pyglet import gl
@@ -274,12 +275,18 @@ def _create_setter_func(
274275
is_matrix,
275276
):
276277
"""Create setters for OpenGL data."""
278+
# Matrix uniforms
277279
if is_matrix:
278280
if ctx._ext_separate_shader_objects_enabled:
279281

280282
def setter_func(value): # type: ignore #conditional function variants must have identical signature
281283
"""Set OpenGL matrix uniform data."""
282-
c_array[:] = value
284+
try:
285+
# FIXME: Configure the struct format on the uniform to support
286+
# other types than float
287+
c_array[:] = struct.unpack(f"{length}f", value)
288+
except Exception:
289+
c_array[:] = value
283290
gl_program_setter(program_id, location, array_length, gl.GL_FALSE, ptr)
284291

285292
else:
@@ -290,6 +297,7 @@ def setter_func(value): # type: ignore #conditional function variants must have
290297
gl.glUseProgram(program_id)
291298
gl_setter(location, array_length, gl.GL_FALSE, ptr)
292299

300+
# Single value uniforms
293301
elif length == 1 and count == 1:
294302
if ctx._ext_separate_shader_objects_enabled:
295303

@@ -306,12 +314,20 @@ def setter_func(value): # type: ignore #conditional function variants must have
306314
gl.glUseProgram(program_id)
307315
gl_setter(location, array_length, ptr)
308316

317+
# Uniforms types with multiple components
309318
elif length > 1 and count == 1:
310319
if ctx._ext_separate_shader_objects_enabled:
311320

312321
def setter_func(values): # type: ignore #conditional function variants must have identical signature
313322
"""Set list of OpenGL uniform data."""
314-
c_array[:] = values
323+
# Support buffer protocol
324+
try:
325+
# FIXME: Configure the struct format on the uniform to support
326+
# other types than float
327+
c_array[:] = struct.unpack(f"{length}f", values)
328+
except Exception:
329+
c_array[:] = values
330+
315331
gl_program_setter(program_id, location, array_length, ptr)
316332

317333
else:

tests/unit/gl/test_gl_program.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import pytest
33
import arcade
44
from pyglet import gl
5-
from pyglet.math import Mat4
5+
from pyglet.math import Mat4, Mat3
66
from arcade.gl import ShaderException
77
from arcade.gl.uniform import UniformBlock
88
from arcade.gl.glsl import ShaderSource
@@ -130,14 +130,15 @@ def test_program_basic(ctx):
130130
vertex_shader="""
131131
#version 330
132132
133+
uniform mat4 matrix;
133134
uniform vec2 pos_offset;
134135
135136
in vec2 in_vert;
136137
in vec2 in_uv;
137138
out vec2 v_uv;
138139
139140
void main() {
140-
gl_Position = vec4(in_vert + pos_offset, 0.0, 1.0);
141+
gl_Position = matrix * vec4(in_vert + pos_offset, 0.0, 1.0);
141142
v_uv = in_uv;
142143
}
143144
""",
@@ -166,6 +167,16 @@ def test_program_basic(ctx):
166167
with pytest.raises(KeyError):
167168
program['this_uniform_do_not_exist']
168169

170+
# uniform values using byte data. struct.unpack in uniform setters will read from
171+
# objects supporting buffer protocol like glm and numpy types
172+
mat44_bytes = b'\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?'
173+
program['matrix'] = mat44_bytes
174+
assert program['matrix'] == Mat4()
175+
176+
# vectors
177+
program['pos_offset'] = b'\x00\x00\x80?\x00\x00\x00@'
178+
assert program['pos_offset'] == (1.0, 2.0)
179+
169180

170181
def test_vertex_shader(ctx):
171182
# Program with only vertex shader

0 commit comments

Comments
 (0)