QOpenGLWidget仅在调整大小时更新 [英] QOpenGLWidget only updates when resized

查看:946
本文介绍了QOpenGLWidget仅在调整大小时更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已获得一个opengl示例,该示例演示如何使用纹理显示2d图像.我已经将示例扩展为在QOpenGLWidget中进行渲染.现在,我要使用QTimer来创建动画.

I've been given an opengl example demonstrating how to use a texture to display a 2d image. I've extended the example to render in a QOpenGLWidget. Now I want to use a QTimer to create an animation.

以下代码应在每次调用paintGL()时将随机生成的16x16灰度图像绘制到纹理上. QTimer每250ms调用一次update(),但是当我调整窗口大小时,我只能看到场景的更新,而我不知道为什么.

The code below should draw a randomly generated 16x16 greyscale image to a texture every time paintGL() is called. A QTimer calls update() every 250ms but I am only seeing updates to the scene when I resize the window and I can't work out why.

我对opengl的经验有限,并且不完全了解绘图代码所做的一切. resizeGL()中是否还需要在paintGL()中包含某些内容?我是否误解了QOpenGLWidget应该如何工作?我应该使用提供的QOpenGLFunctions而不是PyOpenGL吗?

I have limited experience with opengl and don't fully understand everything the drawing code does. Is there something in resizeGL() that needs to be in paintGL() also? Have I misunderstood how QOpenGLWidget is supposed to work? Should I be using the provided QOpenGLFunctions rather than PyOpenGL?

import numpy as np
from PyQt5 import QtCore, QtWidgets
from OpenGL.GL import *
from OpenGL.GL import shaders
from OpenGL.arrays import vbo


class GLWidget(QtWidgets.QOpenGLWidget):

    VERTEX_SHADER = """
        #extension GL_ARB_explicit_attrib_location : enable
        attribute vec4 in_position;
        attribute vec2 in_tex_coord;
        varying vec2 vs_tex_coord;

        void main(void){
            gl_Position = in_position;
            vs_tex_coord = in_tex_coord;
        }"""

    FRAGMENT_SHADER = """
        uniform sampler2D tex;
        varying vec2 vs_tex_coord;

        void main(void){
            gl_FragColor = texture2D(tex, vs_tex_coord);
        }"""

    vbov = vbo.VBO(np.array([[-1.0, -1.0, 0.0, 1.0, 0.0, 0.0],
                             [1.0, -1.0, 0.0, 1.0, 1.0, 0.0],
                             [1.0, 1.0, 0.0, 1.0, 1.0, 1.0],
                             [-1.0, 1.0, 0.0, 1.0, 0.0, 1.0]], 'f'))

    def __init__(self, *args, **kwargs):
        super(GLWidget, self).__init__(*args, **kwargs)
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update)

    def initializeGL(self):
        glClearColor(0, 0, 0, 0)

        vs = shaders.compileShader(self.VERTEX_SHADER, GL_VERTEX_SHADER)
        fs = shaders.compileShader(self.FRAGMENT_SHADER, GL_FRAGMENT_SHADER)
        self.shader = shaders.compileProgram(vs, fs)

        self.position = glGetAttribLocation(self.shader, 'in_position')
        self.tex_coord = glGetAttribLocation(self.shader, 'in_tex_coord')

        self.timer.start(250)

    def paintGL(self):
        print 'paintGL'
        w, h, = 16, 16
        img = np.uint8(np.random.rand(w, h)*255)

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        shaders.glUseProgram(self.shader)
        try:
            self.vbov.bind()
            try:
                tex = glGenTextures(1)
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
                glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img)
                tex_uloc = glGetUniformLocation(self.shader, "tex")
                glUniform1i(tex_uloc, 1)
                glActiveTexture(GL_TEXTURE0)
                glBindTexture(GL_TEXTURE_2D, tex)

                glEnableVertexAttribArray(self.position)
                glEnableVertexAttribArray(self.tex_coord)
                stride = 6 * 4
                glVertexAttribPointer(self.position, 4, GL_FLOAT, False, stride, self.vbov)
                glVertexAttribPointer(self.tex_coord, 2, GL_FLOAT, False, stride, self.vbov + 16)
                glDrawArrays(GL_TRIANGLE_FAN, 0, 4)
            finally:
                self.vbov.unbind()
                glDisableVertexAttribArray(self.position)
                glDisableVertexAttribArray(self.tex_coord)
        finally:
            shaders.glUseProgram(0)

    def resizeGL(self, width, height):
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0.0, width, 0.0, height, -1.0, 1.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()


if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    win = GLWidget()
    win.show()
    app.exec_()

推荐答案

尝试:

id = self.startTimer(time_intervel) in __init__()

然后,实现timerEvent,

then, implement timerEvent,

def timerEvent(self, event):
    self.update()

这篇关于QOpenGLWidget仅在调整大小时更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆