Env:
pyglet - 1.4.2
python - 3.6.6
Background:
For an example there is 160000+ GL_QUADS in a batch, which relates to same pyglet.graphics.TextureGroup
and should have same tex_coords in all period of time.
And for an example there is a logic: each X seconds all these GL_QUADS should change their tex_coords
with new same value.
Problem:
I know only one way to change tex_coords
on vertices - it's iterate through them and explicitly change it like vert.tex_coords = new_text_coords
.
But obviously it will take a long time.
Question:
- How to change
tex_coords
for a huge count of vertices? - Is it possible at all in OpenGL perspective?
Code with example:
rgba.png - is 4*4px image (just an example, real texture could be bigger)
import pyglet
import time
class Window(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.batch = pyglet.graphics.Batch()
self.position = [400, 200, 300.0]
self.collection = []
image = pyglet.image.load("rgba.png") # image is 4px on 4px, just example
image_grid = pyglet.image.ImageGrid(image, 2, 2)
texture_grid = image_grid.get_texture_sequence()
self.texture_group = pyglet.graphics.TextureGroup(texture_grid)
pyglet.graphics.glTexParameteri(
pyglet.graphics.GL_TEXTURE_2D,
pyglet.graphics.GL_TEXTURE_MAG_FILTER,
pyglet.graphics.GL_NEAREST
)
pyglet.graphics.glTexParameteri(
pyglet.graphics.GL_TEXTURE_2D,
pyglet.graphics.GL_TEXTURE_MIN_FILTER,
pyglet.graphics.GL_NEAREST
)
self.tex_map_for_blue_block = texture_grid[0].tex_coords
self.tex_map_for_transparent_block = texture_grid[1].tex_coords
self.tex_map_for_red_block = texture_grid[2].tex_coords
self.tex_map_for_green_block = texture_grid[3].tex_coords
for x in range(400):
for y in range(400):
self.add_vertex_block(x, y)
self.next_color_generator = self.next_color()
pyglet.clock.schedule_interval(self.update, 1 / 2)
def next_color(self):
while True:
yield self.tex_map_for_red_block
yield self.tex_map_for_green_block
yield self.tex_map_for_blue_block
yield self.tex_map_for_transparent_block
def update(self, delta_time):
start = int(time.time() * 1000)
new_text_coords = next(self.next_color_generator)
for vert in self.collection:
vert.tex_coords = new_text_coords
print(f"finish changes in {int(time.time() * 1000) - start}ms")
def add_vertex_block(self, x, y):
x *= 2
y *= 2
tex_coords = ('t3f', self.tex_map_for_red_block)
vertices = self.batch.add(
4, pyglet.gl.GL_QUADS,
self.texture_group,
('v3f', (x, y, 0,
x + 2, y, 0,
x + 2, y + 2, 0,
x, y + 2, 0)
),
tex_coords
)
self.collection.append(vertices)
def set_3d(self):
width, height = self.get_size()
pyglet.graphics.glEnable(pyglet.graphics.GL_BLEND)
pyglet.graphics.glBlendFunc(
pyglet.graphics.GL_SRC_ALPHA,
pyglet.graphics.GL_ONE_MINUS_SRC_ALPHA)
pyglet.graphics.glViewport(0, 0, width, height)
pyglet.graphics.glMatrixMode(pyglet.graphics.GL_PROJECTION)
pyglet.graphics.glLoadIdentity()
pyglet.graphics.gluPerspective(90, width / height, 0.1, 6000.0)
pyglet.graphics.glMatrixMode(pyglet.graphics.GL_MODELVIEW)
pyglet.graphics.glLoadIdentity()
x, y, z = self.position
pyglet.graphics.glTranslatef(-x, -y, -z)
def on_draw(self):
self.clear()
self.set_3d()
self.batch.draw()
if __name__ == '__main__':
window = Window(width=600, height=400, caption='Pyglet', resizable=True)
pyglet.app.run()
Log:
finish changes in 504ms
finish changes in 499ms
finish changes in 498ms
...
What I have tried:
I thought there should be some way to "share" array with used tex_coords
and if values will be changed on initial array - it will lead to changing on vertices's arrays too.
But I was wrong, and as I understand - each vertex has it our array with tex_coords
with is not related to initial self.shared_tex_coords
class Window(pyglet.window.Window):
def __init__():
...
self.shared_tex_coords = [x for x in self.tex_map_for_blue_block]
...
def update(self, delta_time):
new_text_coords = next(self.next_color_generator)
for ind, value in enumerate(new_text_coords):
self.shared_tex_coords[ind] = value
def add_vertex_block(self, x, y):
tex_coords = ('t3f', self.tex_map_for_red_block)
...