OpenGL 纹理 - 一些 jpg 以一种奇怪的方式被扭曲

OpenGL Texturing - some jpg's are being distorted in a strange way

我正在尝试使用 Python、OpenGL 和 GLFW 绘制带纹理的正方形。 这是我要给你看的所有images

抱歉 post 图片的方式,但我没有足够的声誉 post 超过 2 个链接(而且我什至不能 post 一张照片).

我得到这个: [相册中的第二张图片]

取而代之的是: [相册中的第一张图片]

但是如果我使用一些不同的 jpg 文件:

轮换前: [相册中的第三张图片]

旋转后: [相册中的第四张图片]

全靠一个文件。 有人知道我做错了什么吗?还是看到了我没看到的东西?

代码:

首先,我会初始化 glfw,创建 window,等等

if __name__ == '__main__':
    import sys
    import glfw
    import OpenGL.GL as gl
    import numpy as np

    from square import square
    from imio import imread,rgb_flag,swap_rb
    from txio import tx2gpu,txrefer

    glfw.glfwInit()
    win =glfw.glfwCreateWindow(800,800,"Hello")
    glfw.glfwMakeContextCurrent(win)

    glfw.glfwSwapInterval(1)
    gl.glClearColor(0.75,0.75,0.75,1.0)

然后我使用 OpenCV imread 函数加载图像,我记得将红色与蓝色交换。然后我将图像发送到 gpu - 我将在一分钟内描述 tx2gpu。

    image = imread('../imtools/image/ummagumma.jpg')
    if not rgb_flag: swap_rb(image)
    #image = np.rot90(image)
    tx_id = tx2gpu(image)

swap_rb() 函数(在不同的文件中定义,已导入):

def swap_rb(mat):
    X = mat[:,:,2].copy()
    mat[:,:,2] = mat[:,:,0]
    mat[:,:,0] = X
    return mat

然后是主循环(稍后我会描述txrefer和square):

while not glfw.glfwWindowShouldClose(win):
    gl.glClear(gl.GL_COLOR_BUFFER_BIT)
    txrefer(tx_id); square(2); txrefer(0)  
    glfw.glfwSwapBuffers(win)
    glfw.glfwPollEvents()

这里是主要功能的结尾:

glfw.glfwDestroyWindow(win)
glfw.glfwTerminate()

现在重要的事情:

定义正方形的函数如下所示:

def square(scale=1.0,color=None,solid=True):
    s = scale*.5
    if type(color)!=type(None):
        if solid: 
            gl.glBegin(gl.GL_TRIANGLE_FAN)
        else:
            gl.glBegin(gl.GL_LINE_LOOP)
        gl.glColor3f(*color[0][:3]); gl.glVertex3f(-s,-s,0)
        gl.glColor3f(*color[1][:3]); gl.glVertex3f(-s,s,0)
        gl.glColor3f(*color[2][:3]); gl.glVertex3f(s,s,0)
        gl.glColor3f(*color[3][:3]); gl.glVertex3f(s,-s,0)


    else:    
        if solid: 
            gl.glBegin(gl.GL_TRIANGLE_FAN)
        else:
            gl.glBegin(gl.GL_LINE_LOOP)
        gl.glTexCoord2f(0,0); gl.glVertex3f(-s,-s,0)
        gl.glTexCoord2f(0,1); gl.glVertex3f(-s,s,0)
        gl.glTexCoord2f(1,1); gl.glVertex3f(s,s,0)
        gl.glTexCoord2f(1,0); gl.glVertex3f(s,-s,0)
    gl.glEnd()

纹理函数看起来像这样:

import OpenGL.GL as gl

unit_symbols = [
    gl.GL_TEXTURE0,gl.GL_TEXTURE1,gl.GL_TEXTURE2,
    gl.GL_TEXTURE3,gl.GL_TEXTURE4,
    gl.GL_TEXTURE5,gl.GL_TEXTURE6,gl.GL_TEXTURE7,
    gl.GL_TEXTURE8,gl.GL_TEXTURE9,
    gl.GL_TEXTURE10,gl.GL_TEXTURE11,gl.GL_TEXTURE12,
    gl.GL_TEXTURE13,gl.GL_TEXTURE14,
    gl.GL_TEXTURE15,gl.GL_TEXTURE16,gl.GL_TEXTURE17,
    gl.GL_TEXTURE18,gl.GL_TEXTURE19,
    gl.GL_TEXTURE20,gl.GL_TEXTURE21,gl.GL_TEXTURE22,
    gl.GL_TEXTURE23,gl.GL_TEXTURE24,
    gl.GL_TEXTURE25,gl.GL_TEXTURE26,gl.GL_TEXTURE27,
    gl.GL_TEXTURE28,gl.GL_TEXTURE29,
    gl.GL_TEXTURE30,gl.GL_TEXTURE31]

def tx2gpu(image,flip=True,unit=0):
    gl.glActiveTexture(unit_symbols[unit])
    texture_id = gl.glGenTextures(1)
    gl.glBindTexture(gl.GL_TEXTURE_2D,texture_id)


    gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_WRAP_S,gl.GL_REPEAT)
    gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_WRAP_T,gl.GL_REPEAT)
    gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_MAG_FILTER,gl.GL_LINEAR)
    gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_MIN_FILTER,gl.GL_LINEAR)        


    yres,xres,cres = image.shape

    from numpy import flipud
    gl.glTexImage2D(gl.GL_TEXTURE_2D,0,gl.GL_RGB,xres,yres,0,gl.GL_RGB,gl.GL_UNSIGNED_BYTE,flipud(image))


    gl.glBindTexture(gl.GL_TEXTURE_2D,0)
    return texture_id


def txrefer(tex_id,unit=0):
    gl.glColor4f(1,1,1,1);
    gl.glActiveTexture(unit_symbols[unit])
    if tex_id!=0:
        gl.glEnable(gl.GL_TEXTURE_2D)
        gl.glBindTexture(gl.GL_TEXTURE_2D,tex_id)
    else:
        gl.glBindTexture(gl.GL_TEXTURE_2D,0)
        gl.glDisable(gl.GL_TEXTURE_2D)

你遇到的问题是对齐问题。 "unpacking" 图像的 OpenGL 初始对齐设置是每行从 4 字节边界开始。如果图像宽度不是 4 的倍数或者每个像素不是 4 个字节,就会发生这种情况。但改变这个很容易:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1)

可能会为您解决问题。在 glTex[Sub]Image.

之前调用它

另一件事:您的 unit_symbols 列表完全没有必要。 OpenGL 规范明确指出 GL_TEXTUREn = GL_TEXTURE0 + n。你可以简单地做 glActiveTexture(GL_TEXTURE0 + n)。然而,当加载纹理图像时,单位是完全不相关的;唯一可能重要的是,加载纹理只与绑定纹理一起进行,这发生在纹理单元中;纹理可以绑定在任何所需的纹理单元中。

我个人使用最高纹理单元加载图像,以避免意外破坏所需状态。