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()
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()
def __init__(self, display: Union[str, int], qml_view: QUrl, gl_context: QOpenGLContext): super().__init__() self.qml_view = qml_view self.display = display self.wl_display = Display(display) self.wl_compositor = None self.wl_shm = None self.wl_embedder = None self.views = {} self.fd_notifier = None self.engine = Engine() self.component = None self.qml_view = qml_view self.connected = False self.gl_context = gl_context assert gl_context.isOpenGLES() surface = QOffscreenSurface() surface.setFormat(gl_context.format()) surface.create() gl_context.makeCurrent(surface)
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)
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()
def __init__(self, window): self.window = window self.offscreenSurface = QOffscreenSurface() sformat = QSurfaceFormat.defaultFormat() sformat.setDepthBufferSize(32) self.offscreenSurface.setFormat( sformat ) self.offscreenSurface.create() self.overlayCamera = Qt3DRender.QCamera() self.overlayCamera.setViewCenter( vec3d() ) self.overlayCamera.setPosition( vec3d( 0, 0, -1 ) ) self.overlayCamera.setUpVector( vec3d( 0, 1, 0 ) ) self.overlayCamera.lens().setOrthographicProjection( -1, 1, -1, 1, -1, 1 ) # Framegraph root #1 -- onscreen rendering self.surfaceSelector = Qt3DRender.QRenderSurfaceSelector() self.surfaceSelector.setSurface(window) self.root = self.surfaceSelector # Framgraph root #2 -- Used for offscreen renders, not in the graph by default # During screenshots, offscreenSurfaceSelector becomes the root # and the branch roots will become a child of renderTargetSelector self.offscreenSurfaceSelector = Qt3DRender.QRenderSurfaceSelector() self.offscreenSurfaceSelector.setSurface(self.offscreenSurface) self.renderTargetSelector = Qt3DRender.QRenderTargetSelector(self.offscreenSurfaceSelector) self.targetTexture = OffscreenRenderTarget(self.renderTargetSelector) self.renderTargetSelector.setTarget(self.targetTexture) self.noDraw2 = Qt3DRender.QNoDraw(self.renderTargetSelector) # Branch 1: clear buffers self.clearBuffers = Qt3DRender.QClearBuffers(self.surfaceSelector) self.clearBuffers.setBuffers(Qt3DRender.QClearBuffers.ColorDepthBuffer) self.clearBuffers.setClearColor(Qt.white) self.noDraw = Qt3DRender.QNoDraw(self.clearBuffers) # Branch 2: main drawing branches using the Athena camera self.cameraSelector = Qt3DRender.QCameraSelector(self.surfaceSelector) self.cameraSelector.setCamera(window.camera()) # Branch 2A: solid objects self.viewport = Qt3DRender.QViewport(self.cameraSelector) self.viewport.setNormalizedRect(QRectF(0, 0, 1.0, 1.0)) self.qfilt = Qt3DRender.QTechniqueFilter(self.viewport) self.solidPassFilter = Qt3DRender.QFilterKey(self.qfilt) self.solidPassFilter.setName('pass') self.solidPassFilter.setValue('solid') self.qfilt.addMatch(self.solidPassFilter) # Branch 2B: transparent objects self.viewport2 = Qt3DRender.QViewport(self.cameraSelector) self.viewport2.setNormalizedRect(QRectF(0, 0, 1.0, 1.0)) self.qfilt2 = Qt3DRender.QTechniqueFilter(self.viewport2) self.transPassFilter = Qt3DRender.QFilterKey(self.qfilt2) self.transPassFilter.setName('pass') self.transPassFilter.setValue('transp') self.qfilt2.addMatch(self.transPassFilter) # Branch 3: 2D screen overlays self.cameraSelector2 = Qt3DRender.QCameraSelector(self.surfaceSelector) self.cameraSelector2.setCamera(self.overlayCamera) self.viewport3 = Qt3DRender.QViewport(self.cameraSelector2) self.viewport3.setNormalizedRect(QRectF(0, 0, 1.0, 1.0)) self.qfilt3 = Qt3DRender.QTechniqueFilter(self.viewport3) self.overlayPassFilter = Qt3DRender.QFilterKey(self.viewport3) self.overlayPassFilter.setName('pass') self.overlayPassFilter.setValue('overlay') self.qfilt3.addMatch(self.overlayPassFilter) # Branch 4: render capture branch for taking screenshots self.renderCapture = Qt3DRender.QRenderCapture(self.surfaceSelector) self.noDraw3 = Qt3DRender.QNoDraw(self.renderCapture) # Branch roots are the bits that need reparenting when switching between # offscreen and onscreen rendering self.branchRoots = [ self.clearBuffers, self.cameraSelector, self.cameraSelector2, self.renderCapture ]
class AthenaFrameGraph: ''' Class to manage the Qt3D framegraph on behalf of the Athena viewer ''' def __init__(self, window): self.window = window self.offscreenSurface = QOffscreenSurface() sformat = QSurfaceFormat.defaultFormat() sformat.setDepthBufferSize(32) self.offscreenSurface.setFormat( sformat ) self.offscreenSurface.create() self.overlayCamera = Qt3DRender.QCamera() self.overlayCamera.setViewCenter( vec3d() ) self.overlayCamera.setPosition( vec3d( 0, 0, -1 ) ) self.overlayCamera.setUpVector( vec3d( 0, 1, 0 ) ) self.overlayCamera.lens().setOrthographicProjection( -1, 1, -1, 1, -1, 1 ) # Framegraph root #1 -- onscreen rendering self.surfaceSelector = Qt3DRender.QRenderSurfaceSelector() self.surfaceSelector.setSurface(window) self.root = self.surfaceSelector # Framgraph root #2 -- Used for offscreen renders, not in the graph by default # During screenshots, offscreenSurfaceSelector becomes the root # and the branch roots will become a child of renderTargetSelector self.offscreenSurfaceSelector = Qt3DRender.QRenderSurfaceSelector() self.offscreenSurfaceSelector.setSurface(self.offscreenSurface) self.renderTargetSelector = Qt3DRender.QRenderTargetSelector(self.offscreenSurfaceSelector) self.targetTexture = OffscreenRenderTarget(self.renderTargetSelector) self.renderTargetSelector.setTarget(self.targetTexture) self.noDraw2 = Qt3DRender.QNoDraw(self.renderTargetSelector) # Branch 1: clear buffers self.clearBuffers = Qt3DRender.QClearBuffers(self.surfaceSelector) self.clearBuffers.setBuffers(Qt3DRender.QClearBuffers.ColorDepthBuffer) self.clearBuffers.setClearColor(Qt.white) self.noDraw = Qt3DRender.QNoDraw(self.clearBuffers) # Branch 2: main drawing branches using the Athena camera self.cameraSelector = Qt3DRender.QCameraSelector(self.surfaceSelector) self.cameraSelector.setCamera(window.camera()) # Branch 2A: solid objects self.viewport = Qt3DRender.QViewport(self.cameraSelector) self.viewport.setNormalizedRect(QRectF(0, 0, 1.0, 1.0)) self.qfilt = Qt3DRender.QTechniqueFilter(self.viewport) self.solidPassFilter = Qt3DRender.QFilterKey(self.qfilt) self.solidPassFilter.setName('pass') self.solidPassFilter.setValue('solid') self.qfilt.addMatch(self.solidPassFilter) # Branch 2B: transparent objects self.viewport2 = Qt3DRender.QViewport(self.cameraSelector) self.viewport2.setNormalizedRect(QRectF(0, 0, 1.0, 1.0)) self.qfilt2 = Qt3DRender.QTechniqueFilter(self.viewport2) self.transPassFilter = Qt3DRender.QFilterKey(self.qfilt2) self.transPassFilter.setName('pass') self.transPassFilter.setValue('transp') self.qfilt2.addMatch(self.transPassFilter) # Branch 3: 2D screen overlays self.cameraSelector2 = Qt3DRender.QCameraSelector(self.surfaceSelector) self.cameraSelector2.setCamera(self.overlayCamera) self.viewport3 = Qt3DRender.QViewport(self.cameraSelector2) self.viewport3.setNormalizedRect(QRectF(0, 0, 1.0, 1.0)) self.qfilt3 = Qt3DRender.QTechniqueFilter(self.viewport3) self.overlayPassFilter = Qt3DRender.QFilterKey(self.viewport3) self.overlayPassFilter.setName('pass') self.overlayPassFilter.setValue('overlay') self.qfilt3.addMatch(self.overlayPassFilter) # Branch 4: render capture branch for taking screenshots self.renderCapture = Qt3DRender.QRenderCapture(self.surfaceSelector) self.noDraw3 = Qt3DRender.QNoDraw(self.renderCapture) # Branch roots are the bits that need reparenting when switching between # offscreen and onscreen rendering self.branchRoots = [ self.clearBuffers, self.cameraSelector, self.cameraSelector2, self.renderCapture ] #self.dump() def setOffscreenRendering ( self, size = QSize(1200,1200) ): self.targetTexture.setSize(size) for node in self.branchRoots: node.setParent( self.renderTargetSelector ) self.root = self.offscreenSurfaceSelector self.offscreenSurfaceSelector.setExternalRenderTargetSize(size) def setOnscreenRendering (self): for node in self.branchRoots: node.setParent( self.surfaceSelector ) self.root = self.surfaceSelector def dump(self): # Framegraph display and testing code def frameGraphLeaf(node, prefix=' '): print(prefix, node, node.objectName()) children = node.children() for c in children: frameGraphLeaf(c, prefix+'-') frameGraphLeaf(self.root)