You can use BlendDataImages.load()
to load and assign the image in one go:
>>> image = D.images.load("//textures/your_image.exr")
>>> image
bpy.data.images['your_image.exr']
Following demo is based on the given link to the docs:
import bpy
import gpu
import bgl
from gpu_extras.batch import batch_for_shader
image = bpy.data.images.load("//textures/your_image.exr")
shader = gpu.shader.from_builtin('2D_IMAGE')
batch = batch_for_shader(
shader, 'TRI_FAN',
{
"pos": ((100, 100), (200, 100), (200, 200), (100, 200)),
"texCoord": ((0, 0), (1, 0), (1, 1), (0, 1)),
},
)
if image.gl_load():
raise Exception()
def draw():
bgl.glActiveTexture(bgl.GL_TEXTURE0)
bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode)
shader.bind()
shader.uniform_int("image", 0)
batch.draw(shader)
bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')
Modal Draw Operator
Following demo is based on our famous Operator Modal View 3D template that comes with Blender. I'd suggest load the image before calling the actual draw method e.g. as part of invoke
or register
methods... or load it using another operator in the first place.
In order to avoid that Blender loads the same image from disc over and over again, you can pass check_existing=True
to BlendDataImages.load()
or just get the image via D.images.get("your_image.exr")
once loaded:
import bpy
import gpu
import bgl
from gpu_extras.batch import batch_for_shader
import os.path
def draw_callback(self, context):
shader = gpu.shader.from_builtin('2D_IMAGE')
batch = batch_for_shader(
shader, 'TRI_FAN',
{
"pos": ((100, 100), (600, 100), (600, 300), (100, 300)),
"texCoord": ((0, 0), (1, 0), (1, 1), (0, 1)),
},
)
image = self.image
if image.gl_load():
raise Exception()
bgl.glActiveTexture(bgl.GL_TEXTURE0)
bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode)
shader.bind()
shader.uniform_int("image", 0)
batch.draw(shader)
class ModalDrawOperator(bpy.types.Operator):
"""Draw a line with the mouse"""
bl_idname = "view3d.modal_operator"
bl_label = "Simple Modal View3D Operator"
def modal(self, context, event):
context.area.tag_redraw()
if event.type in {'RIGHTMOUSE', 'ESC'}:
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
# Remove the image from the data-blocks
bpy.data.images.remove(self.image)
return {'CANCELLED'}
return {'PASS_THROUGH'} # {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.area.type == 'VIEW_3D':
# Load and assign the image
self.image = bpy.data.images.load("//textures/your_image.exr", check_existing=True)
# Or just get one from the data-blocks
#self.image = bpy.data.images.get("your_image.exr")
# Add the region OpenGL drawing callback
self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback, (self, context), 'WINDOW', 'POST_PIXEL')
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "View3D not found, cannot run operator")
return {'CANCELLED'}
def register():
bpy.utils.register_class(ModalDrawOperator)
def unregister():
bpy.utils.unregister_class(ModalDrawOperator)
if __name__ == "__main__":
register()
Make sure the path to your image is correct (line 44), run the script, press F3 in 3d View, type "Simple Modal View3D ..." and hit Enter. Press ESC to kill the image.