在 OpenGL 中的 3D 模型后面绘制背景视频

Draw a background video behind a 3D model in OpenGL

我正在尝试通过此脚本绘制 3d 模型 (.obj)
https://github.com/yarolig/OBJFileLoader/blob/master/OBJFileLoader/objloader.py
作为 bacg运行d,我想在绘制图像时从 webcam.but 绘制视频,而 3d 模型仅显示图像。
这是我的图片加载器 class

class ImageLoader:

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 0
        self.height = 0
        self.img_data = 0

    def load(self, image):
        im = image
        tx_image = cv2.flip(im, 0)
        tx_image = Image.fromarray(tx_image)
        self.width = tx_image.size[0]
        self.height = tx_image.size[1]
        self.img_data = tx_image.tobytes('raw', 'BGRX', 0, -1)

        self.Texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.Texture)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.width, self.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, self.img_data)

    def draw(self):
        glEnable(GL_TEXTURE_2D)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glTranslate(self.x, self.y, 0)
        glBegin(GL_QUADS)
        glVertex(0, 0, 0)
        glTexCoord2f(0, 0)
        glVertex(self.width, 0, 0)
        glTexCoord2f(0, 1)
        glVertex(self.width, self.height, 0)
        glTexCoord2f(1, 1)
        glVertex(0, self.height, 0)
        glTexCoord2f(1, 0)
        glEnd()
        glDisable(GL_TEXTURE_2D)
        glFlush()

这里是代码 运行.

 if __name__ == '__main__':

    cap = cv2.VideoCapture(0)
    width = int(cap.get(3))
    height = int(cap.get(4))

    pygame.init()
    pygame.display.set_mode((width, height), pygame.DOUBLEBUF | pygame.OPENGL)

    box = OBJ('3dglasses/oculos.obj', ) # from OBJFileLoader import OBJ

    gluPerspective(45, (width / height), 0.1, 50.0)
    glTranslate(0.0, 0.0, -5)
    glRotate(0, 0, 0, 0)

    if True:
        glClearColor(0.7, 0, 0, 1)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(0, width, height, 0)
        im_loader = ImageLoader(0, 0)
        while True:
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()

            success, image = cap.read()
            im_loader.load(image)
            im_loader.draw()

            box.render()
            pygame.display.flip()

图像和模型使用不同的投影和模型视图矩阵。因此,您需要在绘制对象之前设置矩阵。

模型未绘制,因为未通过 Depth Test。 绘制图像时禁用深度测试。如果禁用深度测试,则不会向深度缓冲区写入任何内容。

if __name__ == '__main__':
    cap = cv2.VideoCapture(0)
    width, height = int(cap.get(3)), int(cap.get(4))
    pygame.init()
    pygame.display.set_mode((width, height), pygame.DOUBLEBUF | pygame.OPENGL)
    box = OBJ('3dglasses/oculos.obj', ) # from OBJFileLoader import OBJ
    im_loader = ImageLoader(0, 0)
    angle = 0

    glClearColor(0.7, 0, 0, 1)
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
               run = False

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(0, width, height, 0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

        glDisable(GL_DEPTH_TEST)
        success, image = cap.read()
        if success:
            im_loader.load(image)
        glColor3f(1, 1, 1)
        im_loader.draw()
        
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45, (width / height), 0.1, 50.0)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glTranslate(0.0, 0.0, -5)
        glRotate(angle, 0, 1, 0)
        angle += 1
        
        glEnable(GL_DEPTH_TEST)
        box.render()

        pygame.display.flip()

    pygame.quit()
    quit()

当前纹理坐标,在调用glVertex时与顶点相关联。所以在指定顶点坐标之前需要先指定纹理坐标:

class ImageLoader:
    # [...]

    def draw(self):
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glTranslate(self.x, self.y, 0)
        
        glEnable(GL_TEXTURE_2D)  
        glBegin(GL_QUADS)
        glTexCoord2f(0, 0)
        glVertex2f(0, 0)
        glTexCoord2f(1, 0)
        glVertex2f(self.width, 0)
        glTexCoord2f(1, 1)
        glVertex2f(self.width, self.height)
        glTexCoord2f(0, 1)
        glVertex2f(0, self.height)
        glEnd()
        glDisable(GL_TEXTURE_2D)