VideoWidgetGL

import time

from OpenGL import GL
from PySide6 import QtOpenGLWidgets
from PySide6.QtCore import QTimer
from PySide6.QtOpenGL import QOpenGLTexture, QOpenGLShader, QOpenGLShaderProgram
from timeit import default_timer


class VideoWidget(QtOpenGLWidgets.QOpenGLWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.image_ = None
        self.ori_image = None
        if self.height() != 0:
            self.des_w_h_ratio_ = self.width() / self.height()
        self.src_w_h_ratio_ = float()
        self.scale_w_ = int()
        self.scale_h_ = int()
        self.last = 0.0
        self.texture = None
        # 纹理坐标
        # texCoords.append(QVector2D(0, 1)); # 左上
        # texCoords.append(QVector2D(1, 1)); # 右上
        # texCoords.append(QVector2D(0, 0)); # 左下
        # texCoords.append(QVector2D(1, 0)); # 右下
        # 顶点坐标
        # vertices.append(QVector3D(-1, -1, 1)); # 左下
        # vertices.append(QVector3D(1, -1, 1)); # 右下
        # vertices.append(QVector3D(-1, 1, 1)); # 左上
        # vertices.append(QVector3D(1, 1, 1)); # 右上
        self.texture_coords = [0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0]
        self.vertices = [-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
        self.vshader = None
        self.vsrc = None
        self.fshader = None
        self.fsrc = None
        self.program = None
        self.matrix = None
        self.functions = None
        self.texture_id = None

        # self.timer = QTimer(self)
        # self.timer.timeout.connect(self.on_timeout)
        # self.timer.start(30)
        pass

    def on_timeout(self):
        self.update()

    def init_textures(self):
        self.texture = QOpenGLTexture(QOpenGLTexture.Target2D)
        # self.texture.create()
        # self.texture_id = self.texture.textureId()
        # self.functions.glBindTexture(GL.GL_TEXTURE_2D, self.texture_id)
        # self.functions.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)
        # self.functions.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)
        self.texture.setMinMagFilters(QOpenGLTexture.LinearMipMapLinear, QOpenGLTexture.LinearMipMapLinear)
        self.texture.setMagnificationFilter(QOpenGLTexture.Linear)
        self.texture.setWrapMode(QOpenGLTexture.Repeat)
        self.texture.setSize(self.width(), self.height())
        self.texture.allocateStorage()
        pass

    def init_shaders(self):
        self.vshader = QOpenGLShader(QOpenGLShader.Vertex, self)
        self.vsrc = '''attribute vec4 vertex;                
                attribute vec2 texCoord;
                varying vec2 texc;
                void main(void)
                {
                   gl_Position = vertex;
                   texc = texCoord;
                }'''
        b = self.vshader.compileSourceCode(self.vsrc)  # 编译顶点着色器代码

        self.fshader = QOpenGLShader(QOpenGLShader.Fragment, self)
        self.fsrc = '''uniform sampler2D texture;
                    varying vec2 texc;
                    void main(void)
                    {
                        gl_FragColor = texture2D(texture,texc);
                    }'''
        b = self.fshader.compileSourceCode(self.fsrc)  # 编译纹理着色器代码

        self.program = QOpenGLShaderProgram()
        b = self.program.addShader(self.vshader)  # 添加顶点着色器
        b = self.program.addShader(self.fshader)  # 添加纹理碎片着色器
        b = self.program.bindAttributeLocation("vertex", 0)  # 绑定顶点属性位置
        b = self.program.bindAttributeLocation("texCoord", 1)  # 绑定纹理属性位置
        b = self.program.link()
        # 链接着色器管道
        if not self.program.link():
            self.close()
        # 绑定着色器管道
        if not self.program.bind():
            self.close()
        pass

    def initializeGL(self) -> None:
        # self.initializeOpenGLFunctions() # 初始化OPenGL功能函数
        print(self.getGlInfo())
        self.functions = self.context().functions()
        self.functions.initializeOpenGLFunctions()
        self.functions.glClearColor(0, 0, 0, 0)  # 设置背景为黑色
        self.functions.glEnable(GL.GL_TEXTURE_2D)  # 设置纹理2D功能可用
        self.init_textures()  # 初始化纹理设置
        self.init_shaders()  # 初始化shaders
        pass

    def resizeGL(self, w: int, h: int) -> None:
        self.functions.glViewport(0, 0, w, h)
        pass

    def paintGL(self) -> None:
        self.functions.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)  # 清除屏幕缓存和深度缓冲
        # self.functions.glEnable(GL.GL_BLEND)
        # self.functions.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)

        # self.program.bind()
        self.program.enableAttributeArray(0)
        self.program.enableAttributeArray(1)

        self.program.setAttributeArray(0, self.vertices, 3, 0)
        self.program.setAttributeArray(1, self.texture_coords, 2, 0)
        self.program.setUniformValue("texture", 0)  # 将当前上下文中位置的统一变量设置为value
        self.texture.bind()  # 绑定纹理
        self.functions.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4)  # 绘制纹理
        self.texture.release()  # 释放绑定的纹理
        # self.texture.destroy()  # 消耗底层的纹理对象
        # self.texture.create()
        # self.program.release()
        c = default_timer()
        print("draw cost {}".format(c - self.last))
        self.last = c

    def set_image(self, image):
        if self.texture:
            self.texture.destroy()
            self.texture.create()
            self.texture.setSize(image.width(),image.height(),1)
            self.texture.setData(image)
            # self.texture.setLevelofDetailBias(-1)
            self.repaint()

    def getGlInfo(self):
        "Get opengl info"
        info = """
            Vendor: {0}
            Renderer: {1}
            OpenGL Version: {2}
            Shader Version: {3}
            """.format(
            GL.glGetString(GL.GL_VENDOR),
            GL.glGetString(GL.GL_RENDERER),
            GL.glGetString(GL.GL_VERSION),
            GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)
        )
        return info

posted @ 2022-11-02 09:41  cnblogs_kk  阅读(57)  评论(0)    收藏  举报