Exemplo n.º 1
0
class ExportViewTarget(object):
  def __init__(self, project, filename, parent):
    self.mutex = QMutex()
    self.project = project
    self.filename = filename
    self.parent = parent
    self.surface = QOffscreenSurface()
    self.surface.setFormat(QSurfaceFormat.defaultFormat())
    self.surface.create()

  def destroy(self):
    self.surface.destroy()

  def render(self, view, uniforms=dict()):
    self.project.setCameraMode('view')
    self.project.setCameraViewRef(view)
    self.project.setCameraAtOrigin()
    self.project.render(self.ctx.functions(), view.info.width, view.info.height, uniforms)
    depth = self.project.renderer.depthmap(self.ctx.functions(), view.info.width, view.info.height)
    return depth

  def __enter__(self):
    self.mutex.lock()
    self.ctx = QOpenGLContext()
    self.ctx.setShareContext(self.parent)
    self.ctx.create()
    if not self.ctx.makeCurrent(self.surface):
      raise Exception("cannot make context current")
    self.project.renderer.lock()

  def __exit__(self, type, value, tb):
    self.project.renderer.unlock()
    self.ctx.doneCurrent()
    del self.ctx
    self.mutex.unlock()
Exemplo n.º 2
0
    def initialize(self, size: QSize, shareContext: QOpenGLContext) -> None:
        """
        Initialize offscreen renderer.

        Args:
            size: The size of the area available for rendering.
            shareContext: OpenGL context used as a share context.

        Raises:
            RuntimeError: If the renderer has already been initialized.
        """
        print(f'QmlOffscreenRenderer.initialize: {size}')
        if self.initialized:
            raise RuntimeError('Already initialized')

        context = QOpenGLContext()
        context.setShareContext(shareContext)
        context.setFormat(get_default_format(gles=False))
        context.create()
        assert not context.isOpenGLES(), "We need glGetTexImage from OpenGL"

        self.size = size

        # Create offscreen surface with initialized format
        surface = QOffscreenSurface()
        surface.setFormat(context.format())
        surface.create()
        self.ctx = RenderContext(context, surface)

        # Set up quick rendering
        self._control = control = QQuickRenderControl()
        self._window = window = QQuickWindow(control)
        self._cursor = self._window.cursor()

        # Don't polish/sync/render immediately for better performance, use a timer
        self._renderTimer = renderTimer = QTimer()
        renderTimer.setSingleShot(True)
        renderTimer.setInterval(5)
        renderTimer.timeout.connect(self._onRenderTimer)
        self._syncTimer = syncTimer = QTimer()
        syncTimer.setSingleShot(True)
        syncTimer.setInterval(5)
        syncTimer.timeout.connect(self._onSyncTimer)
        syncTimer.destroyed.connect(self._onSyncTimerDestroyed)

        # Request to create frame buffer
        window.sceneGraphInitialized.connect(self._onSceneGraphInitialized)
        # Request to release frame buffer
        window.sceneGraphInvalidated.connect(self._onSceneGraphInvalidated)
        # Only render is needed
        control.renderRequested.connect(self._onRenderRequested)
        # Polish, sync & render
        control.sceneChanged.connect(self._onSceneChanged)

        self.initialized = True

        # Attach root item
        self.rootItem.setParentItem(self._window.contentItem())
        self._window.contentItem().forceActiveFocus()
        self._updateSizes()
        self.ctx.makeCurrent()
        self._control.initialize(self.ctx.glContext)
Exemplo n.º 3
0
    def initialize(self, size: QSize, shareContext: QOpenGLContext) -> None:
        """
        Initialize offscreen renderer.

        Args:
            size: The size of the area available for rendering.
            shareContext: OpenGL context used as a share context.

        Raises:
            RuntimeError: If the renderer has already been initialized.
        """
        print(f'QmlOffscreenRenderer.initialize: {size}')
        if self.initialized:
            raise RuntimeError('Already initialized')

        format = QSurfaceFormat()
        format.setDepthBufferSize(16)
        format.setStencilBufferSize(8)
        context = QOpenGLContext()
        context.setFormat(format)
        context.setShareContext(shareContext)
        context.create()

        self.size = size
        self.context = context

        # Create offscreen surface with initialized format
        self._surface = surface = QOffscreenSurface()
        surface.setFormat(context.format())
        surface.create()

        # Set up quick rendering
        self._control = control = QQuickRenderControl()
        self._window = window = QQuickWindow(control)
        self._engine = engine = QQmlEngine()
        if not engine.incubationController():
            engine.setIncubationController(window.incubationController())

        # Don't polish/sync/render immediately for better performance, use a timer
        self._renderTimer = renderTimer = QTimer()
        renderTimer.setSingleShot(True)
        renderTimer.setInterval(5)
        renderTimer.timeout.connect(self._onRenderTimer)
        self._syncTimer = syncTimer = QTimer()
        syncTimer.setSingleShot(True)
        syncTimer.setInterval(5)
        syncTimer.timeout.connect(self._onSyncTimer)
        syncTimer.destroyed.connect(self._onSyncTimerDestroyed)

        # Request to create frame buffer
        window.sceneGraphInitialized.connect(self._onSceneGraphInitialized)
        # Request to release frame buffer
        window.sceneGraphInvalidated.connect(self._onSceneGraphInvalidated)
        # Only render is needed
        control.renderRequested.connect(self._onRenderRequested)
        # Polish, sync & render
        control.sceneChanged.connect(self._onSceneChanged)

        self.initialized = True

        # Load QML component
        self._component = component = QQmlComponent(self._engine, self.qmlUrl)
        if component.isLoading():
            component.statusChanged.connect(self._onComponentStatusChanged)
        else:
            self._attachRootItem()