I would like to draw to a GPUOffscreen and render its color texture within the view3d editor but dynamically change its size in relation to the view3d.
The size of the GPUOffscreens can’t be changed at runtime so my I’ve attempted to create a new one each time a draw handler is called. For some reason with this approach the offscreen isn’t rendering. Does anybody know why?
I’m using Blender 2.93.2
Example
import bpy
import gpu
import bgl
from gpu_extras.presets import draw_texture_2d
class DynamicOffScreenDrawer():
def __init__(self):
self.draw_handle = None
def draw(self):
print("drawing offscreen")
context = bpy.context
scene = context.scene
w = int(context.area.width / 2)
h = int(context.area.height / 2)
offscreen = gpu.types.GPUOffScreen(w, h)
self.offscreen = offscreen
view_matrix = scene.camera.matrix_world.inverted()
projection_matrix = scene.camera.calc_matrix_camera(
context.evaluated_depsgraph_get(), x=w, y=h)
offscreen.draw_view3d(
scene,
context.view_layer,
context.space_data,
context.region,
view_matrix,
projection_matrix)
bgl.glDisable(bgl.GL_DEPTH_TEST)
draw_texture_2d(offscreen.color_texture, (10, 10), w, h)
def start(self):
if not self.draw_handle:
self.draw_handle = bpy.types.SpaceView3D.draw_handler_add(self.draw, (), 'WINDOW', 'POST_PIXEL')
def end(self):
if self.draw_handle:
bpy.types.SpaceView3D.draw_handler_remove(self.draw, 'WINDOW')
self.draw_handle = None
offscreendrawer = DynamicOffScreenDrawer()
offscreendrawer.start()
for area in bpy.context.screen.areas:
if area.type == "VIEW_3D":
for region in area.regions:
if region.type == "WINDOW":
region.tag_redraw()
Example of working offscreen drawing but without resizing in relation to the view3d
import bpy
import gpu
import bgl
from gpu_extras.presets import draw_texture_2d
class OffScreenDrawer():
def __init__(self, width, height):
self.draw_handle = None
self.offscreen = gpu.types.GPUOffScreen(width, height)
def draw(self):
print("drawing offscreen")
context = bpy.context
scene = context.scene
offscreen = self.offscreen
view_matrix = scene.camera.matrix_world.inverted()
projection_matrix = scene.camera.calc_matrix_camera(
context.evaluated_depsgraph_get(), x=offscreen.width, y=offscreen.height)
offscreen.draw_view3d(
scene,
context.view_layer,
context.space_data,
context.region,
view_matrix,
projection_matrix)
bgl.glDisable(bgl.GL_DEPTH_TEST)
draw_texture_2d(offscreen.color_texture, (10, 10), offscreen.width, offscreen.height)
def start(self):
if not self.draw_handle:
self.draw_handle = bpy.types.SpaceView3D.draw_handler_add(self.draw, (), 'WINDOW', 'POST_PIXEL')
def end(self):
if self.draw_handle:
bpy.types.SpaceView3D.draw_handler_remove(self.draw, 'WINDOW')
self.draw_handle = None
offscreendrawer = OffScreenDrawer(256, 256)
offscreendrawer.start()
for area in bpy.context.screen.areas:
if area.type == "VIEW_3D":
for region in area.regions:
if region.type == "WINDOW":
region.tag_redraw()
If I run the first example, then run the the second example nothing is drawn also.