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