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

2024-10-02 22:26:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用Python,OpenGL和GLFW绘制一个有纹理的正方形。 这是我要给你看的全部images。在

很抱歉发布图片的方式,但我没有足够的声誉发布超过2个链接(我甚至不能发布照片)。在

我得到了这个: [专辑中的第二张图片]

而不是: [专辑中的第一张图片]

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

  • 其中一些显示正确,

  • 在我将它们旋转90度(我的意思是在带有RGB组件的阵列上使用numpy rot90函数)并将它们发送到GPU之前,它们都会正常显示。看起来是这样的(颜色不变,我只得到一些失真):

旋转前: [专辑中的第三张图片]

旋转后: [专辑中的第四张图片]

这完全取决于一个文件。 有人知道我做错了什么吗?或者看到我看不到的东西?在

代码:

首先,我要初始化glfw,创建一个窗口,等等

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。在

^{pr2}$

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)

Tags: importidif图片unitwincolorsquare
1条回答
网友
1楼 · 发布于 2024-10-02 22:26:53

你遇到的问题是对齐问题。OpenGL对“解包”图像的初始对齐设置是每行从4字节边界开始。如果图像宽度不是4的倍数或每个像素没有4个字节,则会发生这种情况。但要改变这一点很容易:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1)

可能对你有好处。在glTex[Sub]Image之前调用它。在

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

就我个人而言,我使用最高的纹理单位来加载图像,以避免意外地破坏所需的状态。在

相关问题 更多 >