Skip to content

Instantly share code, notes, and snippets.

@wpk-
Created April 30, 2018 07:56
Show Gist options
  • Save wpk-/f5d8e19f66d4f059ccb2b3e914949304 to your computer and use it in GitHub Desktop.
Save wpk-/f5d8e19f66d4f059ccb2b3e914949304 to your computer and use it in GitHub Desktop.
import struct
import moderngl as gl
def test_vao_bind(array_length, loop_count, context):
'''
The program sums the first `count` floats for each vertex.
For example, when `count == 3`, it sums 0 + 1 + 2 = 3 for vertex 1,
3 + 4 + 5 = 12 for vertex 2 and 0 + 0 + 0 = 0 for vertex 3.
The bug happens when array_length == 2 and loop_count == 2. One
would expect the following sums:
vertex 1: 0 + 1 = 1
vertex 2: 3 + 4 = 7
vertex 3: 0 + 0 = 0
OpenGL returns 1, 6, 5 instead. I cannot see how 6 would be a sum of
two consecutive elements.
Args:
array_length: Controls how many elements are passed to the GLSL
float array `arr`. This is either 1, 2 or 3. For values < 3,
the `stride=3*4` argument makes sure to skip the omitted
numbers, so that vertex 2 always starts reading at 3 (index
3) and vertex 3 always starts reading at 0 (index 6).
loop_count: Controls how many numbers are summed. The loop count
should be less than or equal to array length.
'''
assert loop_count <= array_length
arr = (0, 1, 2, # Three floats for vertex 1,
3, 4, 5, # vertex 2, and
0, 0, 0) # three zeros for vertex 3.
buf_a = context.buffer(struct.pack('9f', *arr))
buf_r = context.buffer(struct.pack('3f', 0, 0, 0))
prog = context.program(
vertex_shader='''
#version 400
in float[{SIZE:d}] arr;
out float res;
void main() {{
res = 0;
for (int i=0; i<{COUNT:d}; i++) {{
res += arr[i];
}}
}}
'''.format(SIZE=array_length, COUNT=loop_count),
varyings=['res']
)
vao = context.vertex_array(prog, [(buf_a, '{:d}f'.format(array_length), 'arr')])
vao.bind(prog['arr'].location, 'f', buf_a, '{:d}f'.format(array_length), offset=0, stride=3*4)
vao.transform(buf_r, gl.POINTS, vertices=3)
return struct.unpack('3f', buf_r.read())
if __name__ == '__main__':
ctx = gl.create_standalone_context()
expected_output = {
(1, 1): (0., 3., 0.),
(2, 1): (0., 3., 0.),
(2, 2): (1., 7., 0.),
(3, 1): (0., 3., 0.),
(3, 2): (1., 7., 0.),
(3, 3): (3., 12., 0.),
}
for (length, count), expected in expected_output.items():
result = test_vao_bind(length, count, ctx)
if result == expected:
print((length, count), 'as expected.')
else:
print((length, count), 'expected result', expected,
'but got', result, 'instead.')
@szabolcsdombi
Copy link

    vao = context.vertex_array(prog, [(buf_a, '{:d}f'.format(array_length), 'arr')])
    for i in range(array_length):
        vao.bind(prog['arr'].location + i, 'f', buf_a, 'f', offset=i*4, stride=3*4)

I have no tim e right now, I will explain later

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment