def render(self, camera): self._shader.bind() if self._backface_cull: self._gl.glEnable(self._gl.GL_CULL_FACE) else: self._gl.glDisable(self._gl.GL_CULL_FACE) if self._render_type == self.RenderType.Solid: self._gl.glEnable(self._gl.GL_DEPTH_TEST) self._gl.glDepthMask(self._gl.GL_TRUE) elif self._render_type == self.RenderType.Transparent: self._gl.glEnable(self._gl.GL_DEPTH_TEST) self._gl.glDepthMask(self._gl.GL_FALSE) elif self._render_type == self.RenderType.Overlay: self._gl.glDisable(self._gl.GL_DEPTH_TEST) if self._blend_mode == self.BlendMode.NoBlending: self._gl.glDisable(self._gl.GL_BLEND) elif self._blend_mode == self.BlendMode.Normal: self._gl.glEnable(self._gl.GL_BLEND) self._gl.glBlendFunc(self._gl.GL_SRC_ALPHA, self._gl.GL_ONE_MINUS_SRC_ALPHA) elif self._blend_mode == self.BlendMode.Additive: self._gl.glEnable(self._gl.GL_BLEND) self._gl.glBlendFunc(self._gl.GL_SRC_ALPHA, self._gl.GL_ONE) if self._state_setup_callback: self._state_setup_callback(self._gl) self._view_matrix = camera.getWorldTransformation().getInverse() self._projection_matrix = camera.getProjectionMatrix() self._view_projection_matrix = camera.getProjectionMatrix().multiply(self._view_matrix) self._shader.updateBindings( view_matrix = self._view_matrix, projection_matrix = self._projection_matrix, view_projection_matrix = self._view_projection_matrix, view_position = camera.getWorldPosition(), light_0_position = camera.getWorldPosition() + Vector(0, 50, 0) ) # The VertexArrayObject (VAO) works like a VCR, recording buffer activities in the GPU. # When the same buffers are used elsewhere, one can bind this VertexArrayObject to # the context instead of uploading all buffers again. if OpenGLContext.properties["supportsVertexArrayObjects"]: vao = QOpenGLVertexArrayObject() vao.create() if not vao.isCreated(): Logger.log("e", "VAO not created. Hell breaks loose") vao.bind() for item in self._items: self._renderItem(item) if self._state_teardown_callback: self._state_teardown_callback(self._gl) self._shader.release()
def _vertexBuffersSetup( self, mesh: MeshData) -> Optional[QOpenGLVertexArrayObject]: # See if the mesh has already been stored to the GPU: vao = cast(Optional[QOpenGLVertexArrayObject], mesh.getCachedUserValue(self._shader.getReferenceKey())) if vao is not None: return vao # Initialize VAO (VertexArrayObject). On activation, this will wrap around the other vertex/index buffers. # That enables reusing them without much fuss. if not OpenGLContext.properties["supportsVertexArrayObjects"]: Logger.log( "e", "RenderBatch: This OpenGL doesn't support VAO? You will not go to R^3 today." ) return None vao = QOpenGLVertexArrayObject() vao.create() if not vao.isCreated(): Logger.log( "e", "RenderBatch: VAO not created. You will not go to R^3 today.") return None # Setup VAO: vao.bind() vertex_buffer = OpenGL.getInstance().createVertexBuffer(mesh) vertex_buffer.bind() index_buffer = OpenGL.getInstance().createIndexBuffer(mesh) if index_buffer is not None: index_buffer.bind() self._setMeshAttributes(mesh) # Cache and return: mesh.setCachedUserValue(self._shader.getReferenceKey(), vao) vao.release() return vao