I am writing a simple app that loads an image and displays it on the screen such that the left and right half are rendered separately.
import glm
import moderngl_window
import numpy as np
from PIL import Image
class BugExample(moderngl_window.WindowConfig):
LEFT_TEXTURE_IDX = 0
RIGHT_TEXTURE_IDX = 1
def __init__(self, **kwargs):
super().__init__(**kwargs)
image = Image.open("test.jpg").transpose(Image.FLIP_TOP_BOTTOM)
w, h = image.size
w_even = 2 * (w // 2)
left = image.crop((0, 0, w_even // 2, h))
right = image.crop((w_even // 2, 0, w_even, h))
self.texture_left = self.ctx.texture(left.size, 3, left.tobytes())
self.texture_left.use(self.LEFT_TEXTURE_IDX)
self.texture_right = self.ctx.texture(right.size, 3, right.tobytes())
self.texture_right.use(self.RIGHT_TEXTURE_IDX)
self.program = self.ctx.program(
vertex_shader="""
#version 330
in vec2 in_position;
uniform mat4 model;
out vec2 uv0;
void main() {
gl_Position = model * vec4(in_position, 0.0, 1.0);
uv0 = (0.5 * in_position) + vec2(0.5);
}
""",
fragment_shader="""
#version 330
out vec4 fragColor;
uniform sampler2D texture_idx;
in vec2 uv0;
void main() {
fragColor = texture(texture_idx, uv0);
}
""")
self.left_scale_mat = glm.scale(glm.mat4(), glm.vec3(0.5, 1.0, 1.0))
self.left_translate_mat = glm.translate(glm.mat4(), glm.vec3(-0.5, 0.0, 0.0))
self.left_model_mat = self.left_translate_mat * self.left_scale_mat
self.right_scale_mat = glm.scale(glm.mat4(), glm.vec3(0.5, 1.0, 1.0))
self.right_translate_mat = glm.translate(glm.mat4(), glm.vec3(0.5, 0.0, 0.0))
self.right_model_mat = self.right_translate_mat * self.right_scale_mat
vertices = np.array([-1.0, 1.0, -1.0, -1.0, 1.0, -1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, 1.0], dtype='f4')
self.vbo = self.ctx.buffer(vertices)
self.vao = self.ctx.simple_vertex_array(self.program, self.vbo, 'in_position')
def render(self, time, frame_time):
self.ctx.clear(1.0, 1.0, 1.0)
self.program["model"].write(bytes(self.left_model_mat))
self.program["texture_idx"].value = self.LEFT_TEXTURE_IDX
self.vao.render()
self.program["model"].write(bytes(self.right_model_mat))
self.program["texture_idx"].value = self.RIGHT_TEXTURE_IDX
self.vao.render()
if __name__ == '__main__':
moderngl_window.run_window_config(BugExample, args=('--window', 'glfw'))
Running this program will open a window with your image test.jpg
.
BUT something strange is happening at texture index 31:
If you change the indices such that the texture loaded first (the left texture in our case, as is described in the render
method) has index 31, it will be overridden by the other texture, and you will see the right half repeated twice.
I should point out that if I had only one texture, and not two, and that texture had an index of 31
, there would have been no problem. The problem only arises when there is one texture with index 31
and another texture that is loaded after the 31
texture.
[EDIT: I should also point out that I have no problem loading more than 32 textures. If I was to separate my image into 32 tiles or more (instead of the 2 tiles in the example above), and even 64 tiles or more, the only problem will be with texture index 31
that will be overridden by the last texture loaded.]
I have a vague guess this has something to do with the way the number 31
is manipulated as an int? (like here)
So, finally, my question is - what is happening here?? Am I missing something larger that is happening, or is it just a fact of life and I should avoid texture index 31
and forget about it?