OpenGL 纹理 - 一些 jpg 以一种奇怪的方式被扭曲
OpenGL Texturing - some jpg's are being distorted in a strange way
我正在尝试使用 Python、OpenGL 和 GLFW 绘制带纹理的正方形。
这是我要给你看的所有images。
抱歉 post 图片的方式,但我没有足够的声誉 post 超过 2 个链接(而且我什至不能 post 一张照片).
我得到这个:
[相册中的第二张图片]
取而代之的是:
[相册中的第一张图片]
但是如果我使用一些不同的 jpg 文件:
其中一些显示正常,
在我将它们旋转 90 度(我的意思是在具有 RGB 组件的数组上使用 numpy rot90 函数)然后将它们发送到 GPU 之前,它们中的一些一直在正确显示。看起来像那样(颜色没有改变,我只是有些失真):
轮换前:
[相册中的第三张图片]
旋转后:
[相册中的第四张图片]
全靠一个文件。
有人知道我做错了什么吗?还是看到了我没看到的东西?
代码:
首先,我会初始化 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)
。然而,当加载纹理图像时,单位是完全不相关的;唯一可能重要的是,加载纹理只与绑定纹理一起进行,这发生在纹理单元中;纹理可以绑定在任何所需的纹理单元中。
我个人使用最高纹理单元加载图像,以避免意外破坏所需状态。
我正在尝试使用 Python、OpenGL 和 GLFW 绘制带纹理的正方形。 这是我要给你看的所有images。
抱歉 post 图片的方式,但我没有足够的声誉 post 超过 2 个链接(而且我什至不能 post 一张照片).
我得到这个: [相册中的第二张图片]
取而代之的是: [相册中的第一张图片]
但是如果我使用一些不同的 jpg 文件:
其中一些显示正常,
在我将它们旋转 90 度(我的意思是在具有 RGB 组件的数组上使用 numpy rot90 函数)然后将它们发送到 GPU 之前,它们中的一些一直在正确显示。看起来像那样(颜色没有改变,我只是有些失真):
轮换前: [相册中的第三张图片]
旋转后: [相册中的第四张图片]
全靠一个文件。 有人知道我做错了什么吗?还是看到了我没看到的东西?
代码:
首先,我会初始化 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)
。然而,当加载纹理图像时,单位是完全不相关的;唯一可能重要的是,加载纹理只与绑定纹理一起进行,这发生在纹理单元中;纹理可以绑定在任何所需的纹理单元中。
我个人使用最高纹理单元加载图像,以避免意外破坏所需状态。