Hi here!
I am working on a free blender addon (QuickSnap), and I would like to draw some image in the viewport using the gpu module to give additional information to the user about the current state of the tool.
My plan was to load the image when the modal operator is activated, then draw it using bpy.types.SpaceView3D.draw_handler_add
until the operator is terminated.
And I cannot manage to do it like that. If I do that, the image renders black. I ended up with the help of someone to get that code, that works:
icons = {}
shader_2d_image = gpu.shader.from_builtin('2D_IMAGE')
def draw_image(image):
bgl.glEnable(bgl.GL_BLEND)
if image not in bpy.data.images:
texture_path = Path(os.path.dirname(__file__)) / "icons" / f'{image}.tif'
img = bpy.data.images.load(str(texture_path), check_existing=True)
texture = gpu.texture.from_image(img)
batch = batch_for_shader(
shader_2d_image, 'TRI_FAN',
{
"pos": ((100, 100), (200, 100), (200, 200), (100, 200)),
"texCoord": ((0, 0), (1, 0), (1, 1), (0, 1)),
},
)
shader_2d_image.bind()
shader_2d_image.uniform_sampler("image", texture)
batch.draw(shader_2d_image)
img.reload() #If this line is removed, the texture renders black.
bgl.glDisable(bgl.GL_BLEND)
It is working, BUT as you can read, I need to reload the image at every gpu draw() call.
I can also remove the image from bpy.data.images and load it again… But I would like to avoid loading the image constantly, it sounds like such a waste.
I have also tried loading the image, then storing the result of gpu.texture.from_image(img) in a variable, and using that, but same result: the image is rendered all black.
The strange things is that if I print the read() of that gpu texture, it looks like it contains the right information, but it is not used in the batch.draw() call.