You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 23:08:14