OpenGL无法加载通用图片纹理问题排查求助
OpenGL立方体纹理渲染空白问题排查与解决指导
在OpenGL中尝试将图片纹理应用到3D立方体上时,立方体始终显示空白。已遵循常规纹理加载步骤,尝试过旋转立方体、更换框架、修改图片尺寸(非16x16)、测试不同图片格式均无效;图片设为背景可正常显示,但无法在立方体上渲染。
相关代码
Block纹理与绘制类
from OpenGL.GLU import * from OpenGL.GL import * import os import pygame # 补充缺失的pygame导入 class BlockTexture: def __init__(self, name: str, block_id: int, texture: list): if not isinstance(name, str): raise TypeError("Name must be a string.") if not isinstance(block_id, int): raise TypeError("Block Id must be an integer.") if not isinstance(texture, list) or len(texture) != 3: raise ValueError("Texture must be a list of 3 elements.") self.name = name self.block_id = block_id self.texture = texture def load_texture(self, filepath): textureSurface = pygame.image.load(filepath) # 修复坐标系Y轴翻转问题:Pygame原点在左上角,OpenGL在左下角 textureSurface = pygame.transform.flip(textureSurface, False, True) textureData = pygame.image.tostring(textureSurface, "RGBA", 1) width = textureSurface.get_width() height = textureSurface.get_height() texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texture) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData) return texture def test_texture_file(self): texture_ids = [] for texture in self.texture: if not self.test_texture_filepath(texture): raise ValueError("Invalid texture file path.") texture_file, texture_ext = os.path.splitext(texture) if texture_ext.lower() not in ['.png', '.jpg', '.jpeg']: raise ValueError("Invalid texture file type.") texture_ids.append(self.load_texture(texture)) return texture_ids def test_texture_filepath(self, filepath): if not isinstance(filepath, str): return False if not os.path.isfile(filepath): return False return True class Block(BlockTexture): def __init__(self, name, block_id, texture): super().__init__(name, block_id, texture) self.texture_ids = self.test_texture_file() def draw(self, x, y, z): # Top Face glBindTexture(GL_TEXTURE_2D, self.texture_ids[0]) glBegin(GL_QUADS) glTexCoord2f(0, 1) glVertex3f(x, y + 1, z) glTexCoord2f(1, 1) glVertex3f(x + 1, y + 1, z) glTexCoord2f(1, 0) glVertex3f(x + 1, y + 1, z + 1) glTexCoord2f(0, 0) glVertex3f(x, y + 1, z + 1) glEnd() # Front Face(修正顶点与纹理坐标顺序) glBindTexture(GL_TEXTURE_2D, self.texture_ids[1]) glBegin(GL_QUADS) glTexCoord2f(0, 1) glVertex3f(x, y + 1, z + 1) glTexCoord2f(1, 1) glVertex3f(x + 1, y + 1, z + 1) glTexCoord2f(1, 0) glVertex3f(x + 1, y, z + 1) glTexCoord2f(0, 0) glVertex3f(x, y, z + 1) glEnd() # Back Face(修正顶点与纹理坐标顺序) glBindTexture(GL_TEXTURE_2D, self.texture_ids[1]) glBegin(GL_QUADS) glTexCoord2f(0, 1) glVertex3f(x + 1, y + 1, z) glTexCoord2f(1, 1) glVertex3f(x, y + 1, z) glTexCoord2f(1, 0) glVertex3f(x, y, z) glTexCoord2f(0, 0) glVertex3f(x + 1, y, z) glEnd() # Left face(修正顶点与纹理坐标顺序) glBindTexture(GL_TEXTURE_2D, self.texture_ids[1]) glBegin(GL_QUADS) glTexCoord2f(0, 1) glVertex3f(x, y + 1, z) glTexCoord2f(1, 1) glVertex3f(x, y + 1, z + 1) glTexCoord2f(1, 0) glVertex3f(x, y, z + 1) glTexCoord2f(0, 0) glVertex3f(x, y, z) glEnd() # Right face(修正顶点与纹理坐标顺序) glBindTexture(GL_TEXTURE_2D, self.texture_ids[1]) glBegin(GL_QUADS) glTexCoord2f(0, 1) glVertex3f(x + 1, y + 1, z + 1) glTexCoord2f(1, 1) glVertex3f(x + 1, y + 1, z) glTexCoord2f(1, 0) glVertex3f(x + 1, y, z) glTexCoord2f(0, 0) glVertex3f(x + 1, y, z + 1) glEnd() # Bottom face(修正顶点与纹理坐标顺序) glBindTexture(GL_TEXTURE_2D, self.texture_ids[0]) glBegin(GL_QUADS) glTexCoord2f(0, 0) glVertex3f(x, y, z) glTexCoord2f(1, 0) glVertex3f(x + 1, y, z) glTexCoord2f(1, 1) glVertex3f(x + 1, y, z + 1) glTexCoord2f(0, 1) glVertex3f(x, y, z + 1) glEnd()
测试主函数
import pygame from pygame.locals import * def test_pygame_opengl(): pygame.init() display = (800, 600) pygame.display.set_mode(display, DOUBLEBUF|OPENGL) # 启用核心OpenGL功能 glEnable(GL_TEXTURE_2D) # 必须开启纹理映射 glEnable(GL_DEPTH_TEST) # 开启深度测试避免面遮挡 gluPerspective(45, (display[0]/display[1]), 0.1, 50.0) glTranslatef(0.0, 0.0, -5) GrassBlock = Block( name="grass_block", block_id=1, texture=[ "grass_block_top16x16.png", "grass_block_side16x16.png", "grass_block_bottom16x16.png" ]) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() glRotatef(1, 3, 1, 1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) GrassBlock.draw(0, 0, 0) pygame.display.flip() pygame.time.wait(10) test_pygame_opengl()
核心问题与解决要点
- 必须启用纹理映射:OpenGL默认关闭纹理功能,初始化时需调用
glEnable(GL_TEXTURE_2D),否则纹理绑定不会生效。 - 修正纹理Y轴翻转:Pygame与OpenGL的坐标系Y轴方向相反,加载纹理时需用
pygame.transform.flip翻转Y轴,否则纹理会上下颠倒或无法正确显示。 - 调整顶点与纹理坐标顺序:原代码中部分面的顶点顺序和纹理坐标不匹配,导致纹理被拉伸或不可见,需确保每个顶点对应的纹理坐标顺序一致(如顺时针排列)。
- 启用深度测试:添加
glEnable(GL_DEPTH_TEST),避免立方体的面互相遮挡,导致纹理被覆盖显示空白。 - 补充缺失的导入:
BlockTexture类的load_texture方法依赖pygame,需在类文件顶部补充导入import pygame。
内容的提问来源于stack exchange,提问作者user20983853
相关产品推荐
相关产品推荐

