Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorDalai Felinto <dfelinto@gmail.com>2018-09-21 01:06:51 +0300
committerDalai Felinto <dfelinto@gmail.com>2018-09-21 01:21:19 +0300
commitfbc837b2f8e165f313a16843cfef54620a6d86d3 (patch)
treece513809b5ac1aec79cf20f8eadacf3f4e021ee7 /doc
parent5340e9ac1b4f4553b0235ab5016b6cda4254ab63 (diff)
Updated gpu.types.GPUOffscreen.py example file
The image I get is a bit too dark, which is the same I get in the viewport itself when there is no Display Device. So I believe for cases like this we need to have color management on top of the buffer. Also, on EEVEE it looks like it needs to clear some extra buffers. You can see that, by rotating the camera view around. That said, this is the first step to bring back fun addons that use external offscreen buffers. Note: When using gpu offscreen with POST_VIEW (as oppose to POST_PIXEL) I get a crash with DST having 0xFF..
Diffstat (limited to 'doc')
-rw-r--r--doc/python_api/examples/gpu.types.GPUOffScreen.py207
1 files changed, 139 insertions, 68 deletions
diff --git a/doc/python_api/examples/gpu.types.GPUOffScreen.py b/doc/python_api/examples/gpu.types.GPUOffScreen.py
index a1b38837278..b7f11b94a11 100644
--- a/doc/python_api/examples/gpu.types.GPUOffScreen.py
+++ b/doc/python_api/examples/gpu.types.GPUOffScreen.py
@@ -1,16 +1,58 @@
# Draws an off-screen buffer and display it in the corner of the view.
import bpy
-from bgl import *
-
-
-class OffScreenDraw(bpy.types.Operator):
+import bgl
+import gpu
+import numpy as np
+
+g_imageVertSrc = '''
+in vec2 texCoord;
+in vec2 pos;
+
+out vec2 texCoord_interp;
+
+void main()
+{
+ gl_Position = vec4(pos.xy, 0.0f, 1.0);
+ gl_Position.z = 1.0f;
+ texCoord_interp = texCoord;
+}
+'''
+
+g_imageFragSrc = '''
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp);
+}
+'''
+
+g_plane_vertices = np.array([
+ ([-1.0, -1.0], [0.0, 0.0]),
+ ([1.0, -1.0], [1.0, 0.0]),
+ ([1.0, 1.0], [1.0, 1.0]),
+ ([1.0, 1.0], [1.0, 1.0]),
+ ([-1.0, 1.0], [0.0, 1.0]),
+ ([-1.0, -1.0], [0.0, 0.0]),
+], [('pos', 'f4', 2), ('uv', 'f4', 2)])
+
+
+class VIEW3D_OT_draw_offscreen(bpy.types.Operator):
bl_idname = "view3d.offscreen_draw"
- bl_label = "View3D Offscreen Draw"
+ bl_label = "Viewport Offscreen Draw"
_handle_calc = None
_handle_draw = None
is_enabled = False
+ global_shader = None
+ batch_plane = None
+ uniform_image = -1
+ shader = None
+
# manage draw handler
@staticmethod
def draw_callback_px(self, context):
@@ -22,22 +64,21 @@ class OffScreenDraw(bpy.types.Operator):
@staticmethod
def handle_add(self, context):
- OffScreenDraw._handle_draw = bpy.types.SpaceView3D.draw_handler_add(
+ VIEW3D_OT_draw_offscreen._handle_draw = bpy.types.SpaceView3D.draw_handler_add(
self.draw_callback_px, (self, context),
'WINDOW', 'POST_PIXEL',
)
@staticmethod
def handle_remove():
- if OffScreenDraw._handle_draw is not None:
- bpy.types.SpaceView3D.draw_handler_remove(OffScreenDraw._handle_draw, 'WINDOW')
+ if VIEW3D_OT_draw_offscreen._handle_draw is not None:
+ bpy.types.SpaceView3D.draw_handler_remove(VIEW3D_OT_draw_offscreen._handle_draw, 'WINDOW')
- OffScreenDraw._handle_draw = None
+ VIEW3D_OT_draw_offscreen._handle_draw = None
# off-screen buffer
@staticmethod
def _setup_offscreen(context):
- import gpu
scene = context.scene
aspect_ratio = scene.render.resolution_x / scene.render.resolution_y
@@ -58,86 +99,96 @@ class OffScreenDraw(bpy.types.Operator):
modelview_matrix = camera.matrix_world.inverted()
projection_matrix = camera.calc_matrix_camera(
- render.resolution_x,
- render.resolution_y,
- render.pixel_aspect_x,
- render.pixel_aspect_y,
+ context.depsgraph,
+ x=render.resolution_x,
+ y=render.resolution_y,
+ scale_x=render.pixel_aspect_x,
+ scale_y=render.pixel_aspect_y,
)
offscreen.draw_view3d(
scene,
- render_layer,
+ view_layer,
context.space_data,
context.region,
projection_matrix,
modelview_matrix,
)
- @staticmethod
- def _opengl_draw(context, texture, aspect_ratio, scale):
+ def _opengl_draw(self, context, texture, aspect_ratio, scale):
"""
OpenGL code to draw a rectangle in the viewport
"""
-
- glDisable(GL_DEPTH_TEST)
-
# view setup
- glMatrixMode(GL_PROJECTION)
- glPushMatrix()
- glLoadIdentity()
+ bgl.glDisable(bgl.GL_DEPTH_TEST)
- glMatrixMode(GL_MODELVIEW)
- glPushMatrix()
- glLoadIdentity()
+ viewport = bgl.Buffer(bgl.GL_INT, 4)
+ bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport)
- glOrtho(-1, 1, -1, 1, -15, 15)
- gluLookAt(0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
-
- act_tex = Buffer(GL_INT, 1)
- glGetIntegerv(GL_TEXTURE_2D, act_tex)
-
- viewport = Buffer(GL_INT, 4)
- glGetIntegerv(GL_VIEWPORT, viewport)
+ active_texture = bgl.Buffer(bgl.GL_INT, 1)
+ bgl.glGetIntegerv(bgl.GL_TEXTURE_2D, active_texture)
width = int(scale * viewport[2])
height = int(width / aspect_ratio)
- glViewport(viewport[0], viewport[1], width, height)
- glScissor(viewport[0], viewport[1], width, height)
+ bgl.glViewport(viewport[0], viewport[1], width, height)
+ bgl.glScissor(viewport[0], viewport[1], width, height)
# draw routine
- glEnable(GL_TEXTURE_2D)
- glActiveTexture(GL_TEXTURE0)
+ batch_plane = self.get_batch_plane()
- glBindTexture(GL_TEXTURE_2D, texture)
+ shader = VIEW3D_OT_draw_offscreen.shader
+ # bind it so we can pass the new uniform values
+ shader.bind()
- texco = [(1, 1), (0, 1), (0, 0), (1, 0)]
- verco = [(1.0, 1.0), (-1.0, 1.0), (-1.0, -1.0), (1.0, -1.0)]
+ bgl.glEnable(bgl.GL_TEXTURE_2D)
+ bgl.glActiveTexture(bgl.GL_TEXTURE0)
+ bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture)
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
+ shader.uniform_int(VIEW3D_OT_draw_offscreen.uniform_image, 0)
+ batch_plane.draw()
- glColor4f(1.0, 1.0, 1.0, 1.0)
+ # restoring settings
+ bgl.glBindTexture(bgl.GL_TEXTURE_2D, active_texture[0])
+ bgl.glDisable(bgl.GL_TEXTURE_2D)
- glBegin(GL_QUADS)
- for i in range(4):
- glTexCoord3f(texco[i][0], texco[i][1], 0.0)
- glVertex2f(verco[i][0], verco[i][1])
- glEnd()
+ # reset view
+ bgl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3])
+ bgl.glScissor(viewport[0], viewport[1], viewport[2], viewport[3])
- # restoring settings
- glBindTexture(GL_TEXTURE_2D, act_tex[0])
+ def get_batch_plane(self):
+ if self.batch_plane is None:
+ global g_plane_vertices
- glDisable(GL_TEXTURE_2D)
+ format = gpu.types.GPUVertFormat()
+ pos_id = format.attr_add(
+ id="pos",
+ comp_type="F32",
+ len=2,
+ fetch_mode="FLOAT")
- # reset view
- glMatrixMode(GL_PROJECTION)
- glPopMatrix()
+ uv_id = format.attr_add(
+ id="texCoord",
+ comp_type="F32",
+ len=2,
+ fetch_mode="FLOAT")
- glMatrixMode(GL_MODELVIEW)
- glPopMatrix()
+ vbo = gpu.types.GPUVertBuf(
+ len=len(g_plane_vertices),
+ format=format)
- glViewport(viewport[0], viewport[1], viewport[2], viewport[3])
- glScissor(viewport[0], viewport[1], viewport[2], viewport[3])
+ vbo.fill(id=pos_id, data=g_plane_vertices["pos"])
+ vbo.fill(id=uv_id, data=g_plane_vertices["uv"])
+
+ batch_plane = gpu.types.GPUBatch(type="TRIS", buf=vbo)
+ shader = self.global_shader
+
+ VIEW3D_OT_draw_offscreen.shader = shader
+ VIEW3D_OT_draw_offscreen.uniform_image = shader.uniform_from_name("image")
+
+ batch_plane.program_set(shader)
+ VIEW3D_OT_draw_offscreen.batch_plane = batch_plane
+ return VIEW3D_OT_draw_offscreen.batch_plane
# operator functions
@classmethod
@@ -148,24 +199,26 @@ class OffScreenDraw(bpy.types.Operator):
if context.area:
context.area.tag_redraw()
+ if event.type in {'RIGHTMOUSE', 'ESC'}:
+ self.cancel(context)
+ return {'CANCELLED'}
+
return {'PASS_THROUGH'}
def invoke(self, context, event):
- if OffScreenDraw.is_enabled:
+ if VIEW3D_OT_draw_offscreen.is_enabled:
self.cancel(context)
-
return {'FINISHED'}
-
else:
- self._offscreen = OffScreenDraw._setup_offscreen(context)
+ self._offscreen = VIEW3D_OT_draw_offscreen._setup_offscreen(context)
if self._offscreen:
self._texture = self._offscreen.color_texture
else:
self.report({'ERROR'}, "Error initializing offscreen buffer. More details in the console")
return {'CANCELLED'}
- OffScreenDraw.handle_add(self, context)
- OffScreenDraw.is_enabled = True
+ VIEW3D_OT_draw_offscreen.handle_add(self, context)
+ VIEW3D_OT_draw_offscreen.is_enabled = True
if context.area:
context.area.tag_redraw()
@@ -174,20 +227,38 @@ class OffScreenDraw(bpy.types.Operator):
return {'RUNNING_MODAL'}
def cancel(self, context):
- OffScreenDraw.handle_remove()
- OffScreenDraw.is_enabled = False
+ VIEW3D_OT_draw_offscreen.handle_remove()
+ VIEW3D_OT_draw_offscreen.is_enabled = False
+
+ if VIEW3D_OT_draw_offscreen.batch_plane is not None:
+ del VIEW3D_OT_draw_offscreen.batch_plane
+ VIEW3D_OT_draw_offscreen.batch_plane = None
+
+ VIEW3D_OT_draw_offscreen.shader = None
if context.area:
context.area.tag_redraw()
def register():
- bpy.utils.register_class(OffScreenDraw)
+ if hasattr(bpy.types, "VIEW3D_OT_draw_offscreen"):
+ del VIEW3D_OT_draw_offscreen.global_shader
+
+ shader = gpu.types.GPUShader(g_imageVertSrc, g_imageFragSrc)
+ VIEW3D_OT_draw_offscreen.global_shader = shader
+
+ bpy.utils.register_class(VIEW3D_OT_draw_offscreen)
def unregister():
- bpy.utils.unregister_class(OffScreenDraw)
+ bpy.utils.unregister_class(VIEW3D_OT_draw_offscreen)
+ VIEW3D_OT_draw_offscreen.global_shader = None
if __name__ == "__main__":
+ try:
+ unregister()
+ except RuntimeError:
+ pass
+
register()