纹理不起作用

Textures not working

很好。那个 OpenGL 状态机在开玩笑!我是认真的!就在几天前,所有人都在立即模式甚至 VBO 模式下工作,但今天不行!今天我看到了一个白色的四边形,因为我重写了 80% 的旧代码。那真是太酷了,你知道的。
所以。我需要你们的帮助。这是我的 GL 调用跟踪器输出:

[17.02.2015 17:45:47] [--------GAME_STARTED--------]
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_COLOR_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_TEXTURE_2D) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_TEXTURE_COORD_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_VERTEX_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_INDEX_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_NORMAL_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_NORMALIZE) -> false
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_MATRIX_MODE) -> GL_MODELVIEW
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_DEPTH_TEST) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_ALPHA_TEST) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_STENCIL_TEST) -> false
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_DEPTH_FUNC) -> GL_LESS
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_CULL_FACE_MODE) -> GL_BACK
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_BLEND) -> false
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_ARRAY_BUFFER_BINDING) -> 0
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING) -> 0
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_TEXTURE_BINDING_2D) -> GL_CURRENT_BIT
[17.02.2015 17:45:49] [GLTrace] glEnable(GL_DEPTH_TEST) -> DONE
[17.02.2015 17:45:49] [GLTrace] glDisable(GL_CULL_FACE) -> DONE
[17.02.2015 17:45:49] [GLTrace] glCullFace(Off) -> DONE
[17.02.2015 17:45:49] [GLTrace] glDepthFunc(LessOrEqual) -> DONE
[17.02.2015 17:45:49] [GLTrace] glBindBuffer(VertexArray, -1) -> DONE
[17.02.2015 17:45:49] [GLTrace] glBindBuffer(ElementArray, -1) -> DONE
[17.02.2015 17:45:49] [GLTrace] glBindTexture(Texture2D, -1) -> DONE
[17.02.2015 17:45:49] [GLTrace] glViewport(0, 0, 800, 600) -> DONE
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_MAX_TEXTURE_SIZE, java.nio.DirectIntBufferU[pos=0 lim=16 cap=16]) -> DONE
[17.02.2015 17:45:49] [GLTrace] glGenTextures() -> 2
[17.02.2015 17:45:49] [GLTrace] glBindTexture(Texture2D, 2) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_BASE_LEVEL, 0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_MAX_LEVEL, 0) -> DONE
[17.02.2015 17:45:49] [GLTrace] [Setting wrap mode: Clamp]
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_WRAP_S, GL_CLAMP) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_WRAP_T, GL_CLAMP) -> DONE
[17.02.2015 17:45:49] [GLTrace]  -> DONE
[17.02.2015 17:45:49] [GLTrace] [Setting filter mode: Nearest]
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) -> DONE
[17.02.2015 17:45:49] [GLTrace]  -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexImage2D(Texture2D, 0, RGBA, 256, 256, 0, RGBA, UnsignedByte, java.nio.DirectByteBuffer[pos=0 lim=262144 cap=262144]) -> DONE
[17.02.2015 17:45:49] [GLTrace] glClear(ColorAndDepth) -> DONE
[17.02.2015 17:45:49] [GLTrace] glLoadIdentity() -> DONE
[17.02.2015 17:45:49] [GLTrace] glMatrixMode(Projection) -> DONE
[17.02.2015 17:45:49] [GLTrace] glLoadIdentity() -> DONE
[17.02.2015 17:45:49] [GLTrace] gluPerspective(70.0, 1.3333334, 0.001, 5000.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glMatrixMode(ModelView) -> DONE
[17.02.2015 17:45:49] [GLTrace] glPushMatrix() -> DONE
[17.02.2015 17:45:49] [GLTrace] glBegin(Quads) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexCoord2f(0.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glVertex3f(0.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexCoord2f(1.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glVertex3f(1.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexCoord2f(1.0, 1.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glVertex3f(1.0, 1.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexCoord2f(0.0, 1.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glVertex3f(0.0, 1.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glEnd() -> DONE
[17.02.2015 17:45:49] [GLTrace] glPopMatrix() -> DONE
[17.02.2015 17:45:49] [GLTrace] glLoadIdentity() -> DONE
[17.02.2015 17:45:49] [GLTrace] glMatrixMode(Projection) -> DONE
[17.02.2015 17:45:49] [GLTrace] gluOrtho2D(0.0, 800.0, 600.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glMatrixMode(ModelView) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTranslatef(0.375, 0.375, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glDisable(GL_DEPTH_TEST) -> DONE
[17.02.2015 17:45:49] [GLTrace] glBindTexture(Texture2D, -1) -> DONE
[17.02.2015 17:45:49] [---------GAME_ENDED---------]

这是我的即时模式四边形渲染 - 全白! 为什么会这样?我很确定 slick-util 正确加载了图像。图片有效(两天前刚测试过)。我可能做了一些更改(全局渲染系统重构:3)...我没有使用 slick-util Texture 和 TextureImpl。我也没有使用 mipmaps。

这是我对那段代码的实现:

public class Texture
{

    protected int width, height, texWidth, texHeight, depth;
    protected boolean alpha;
    protected WrapMode wrapMode = WrapMode.Clamp;
    protected FilterMode filterMode = FilterMode.Nearest;
    protected TextureBuffer buffer;
    protected PixelFormat dstPixelFormat = PixelFormat.RGBA, srcPixelFormat;

    public Texture(LoadableImageData imageData, WrapMode wrapMode, FilterMode filterMode)
    {
        this.width = imageData.getWidth();
        this.height = imageData.getHeight();
        this.texWidth = imageData.getTexWidth();
        this.texHeight = imageData.getTexHeight();
        this.depth = imageData.getDepth();
        this.wrapMode = wrapMode;
        this.filterMode = filterMode;
        this.alpha = depth == 32;
        this.srcPixelFormat = alpha ? PixelFormat.RGBA : PixelFormat.RGB;

        buffer = (TextureBuffer) BufferManager.create(BufferType.Texture);
        BufferManager.setup(this, imageData.getImageBufferData(), srcPixelFormat.getSize());
    }

    public int getWidth()
    {
        return width;
    }

    public int getHeight()
    {
        return height;
    }

    public TextureBuffer getBuffer()
    {
        return buffer;
    }

    public WrapMode getWrapMode()
    {
        return wrapMode;
    }

    public FilterMode getFilterMode()
    {
        return filterMode;
    }

    public PixelFormat getDstPixelFormat()
    {
        return dstPixelFormat;
    }

    public PixelFormat getSrcPixelFormat()
    {
        return srcPixelFormat;
    }
}

这是重做的纹理加载器:

public class TextureLoader
{

    private static IntBuffer maxResolutionBuffer;

    public static LoadableImageData loadImage(String resourceName)
    {
        LoadableImageData imageData = ImageDataFactory.getImageDataFor(resourceName);
        ByteBuffer data = null;
        try {
            data = imageData.loadImage(new BufferedInputStream(new FileInputStream(new File("res", resourceName))),
                                       false, null);
        } catch (FileNotFoundException ex) {
            FaultManager.process("Can't find image!", ex, true);
        } catch (IOException ex) {
            FaultManager.process("Can't load image!", ex, true);
        }
        return imageData;
    }

    public static Texture getTexture(LoadableImageData imageData, WrapMode wrap, FilterMode filter) throws IOException
    {
        if (!checkTextureResolution(imageData.getTexWidth(), imageData.getTexHeight())) {
            throw new IOException("Attempt to allocate a texture too big for the current hardware");
        }
        return new Texture(imageData, wrap, filter);
    }

    public static boolean checkTextureResolution(int texWidth, int texHeight)
    {
        if (maxResolutionBuffer == null) {
            maxResolutionBuffer = BufferUtils.createIntBuffer(16);
            GLProxy.getProperty(GL11.GL_MAX_TEXTURE_SIZE, GLProxy.GLParamType.Integer, maxResolutionBuffer);
        }
        int max = maxResolutionBuffer.get(0);
        if ((texWidth > max) || (texHeight > max)) {
            return false;
        }
        return true;
    }
}

在我的游戏代码中,我只是使用:

        try {
            LoadableImageData imageData = TextureLoader.loadImage("test.png");
            texture = TextureLoader.getTexture(imageData, WrapMode.Clamp, FilterMode.Nearest);
        } catch (IOException ex) {
            FaultManager.process("Can't load texture test.png!", ex, true);
        }

所有其他 类 实现了他们自己的东西,我很确定你可以在 GLTrace 中找到它。

好的。这与即时模式渲染和缓冲对象一起工作。 这也像魔术一样发生了。通过启用 GL_TEXTURE_2D(怪我自己)并禁用 GL_VERTEX_ARRAY 和 GL_INDEX_ARRAY 修复了即时模式渲染。这次我刚试过之后,VBO 就修好了。我认为这是我的状态改变错误,导致纹理和数组之前默认启用。所以我不确定这次我是如何修复 VBO 的,但我很自豪地说 "Whosebug" 仍然有一些新鲜的想法!感谢@Jean-SimonBrochu!

OpenGL的主要问题
它与函数式编程或状态编程一起使用。这意味着每次错过一个电话或传递错误数据时,OpenGL 上下文(您使用 Display 创建)都会让您哭泣。首先 - 如果不重要,即使不设置错误状态它也可以工作。其次 - 你的 JVM 将被 JNI 破坏,导致本机代码 (C++/Asm) 崩溃。

这是我对如何处理这个问题的简短建议:

  1. 控制 OOP 中的一切(您应该实施 classes 来控制与任何 GL 调用等对应的进程)
  2. 控制 GL 状态(您应该实现一个 data/option 容器 class,它将包含抽象的或当前的 OpenGL 状态)
  3. 每当您不确定到底发生了什么时,请使用 glGetError。您应该在对 OpenGL 进行可疑调用后立即使用此函数。
  4. 始终构建易于理解的系统。总是!即使你为自己做项目。这会浪费可能试图帮助您了解您的垃圾作品的人的时间。
  5. 处理您自己可以访问的所有工作部分。致力于实现这一点将向您展示整个系统是如何工作的,并帮助您调整您对系统的想法以适应这一点。

纹理不工作?检查这个!

  1. 检查您是否启用了 GL_TEXTURE_2D(或 GL_TEXTURE 在真正的旧版本中)。您必须确保您以后不会禁用它!
  2. 选中与您选择的一种渲染模式对应的所有 GL 状态选项。我的意思是,如果你使用的是 VBO,你还应该启用 GL_VERTEX_ARRAY 等你使用的。
  3. 检查您的纹理坐标 (texCoords) 是否已正确设置并启用了纹理坐标数组选项。
  4. 检查您是否生成了 mipmap 或根本不使用它们。默认情况下,OpenGL 状态设置为使用 mipmap。您可以通过采用正确的纹理过滤模式(GL_NEAREST/GL_LINEAR 或 GL_NEAREST_MIPMAP_NEAREST/GL_LINEAR_MIPMAP_LINEAR)来切换它。
  5. 如果您的图像使用 Alpha 通道,请检查您是否设置了 GL_BLEND 并将混合模式设置为 Alpha 到 GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA。
  6. 检查您的网格上的法线是否正确(如果您使用它们)。
  7. 最后检查您的传入数据(图像)。这很难,但如果您遵循上述第 5 页的建议 - 那应该相当容易。

谢谢。尝试变得有用,并得出更多的答案而不是问题的缺点:)

那是我在 GLState 中的问题 class:

-   public boolean depthTest = true;
+   public boolean depthTest = false;
-   public boolean vertexArray = true, indexArray = true, colorArray = false, textureArray = false, normalArray = false;
+   public boolean vertexArray, indexArray, colorArray, textureArray, normalArray;

static {
+       DEFAULT_3D.depthTest = true;
+       DEFAULT_3D.vertexArray = true;
+       DEFAULT_3D.indexArray = true;
+
+       DEBUG_3D.depthTest = true;
+       DEBUG_3D.vertexArray = true;
+       DEBUG_3D.indexArray = true;
        DEBUG_3D.faceCullingMode = FaceCullingMode.Off;
}

P.S。 LWJGL 2.9.1

的说明