为什么纹理图像颜色与原点不同?

Why do the textured image colors are not the same as the origin?

我正在使用 LWJGL(Java 的 OpenGL)库进行纹理映射。 这是从文件中读取图像的代码:

BufferedImage image = ImageIO.read(new File(url));

获取数据栅格(图像像素)作为字节数组的代码:

DataBufferByte imageByteBuffer = ((DataBufferByte)image.getRaster().getDataBuffer());
byte[] bytePixels = imageByteBuffer.getData();

现在是创建 "bytePixels" 数组并将其放入字节缓冲区的代码:

pixels = BufferUtils.createByteBuffer(bytePixels.length);
pixels.put(bytePixels);
pixels.flip();

此处用于将所有内容绑定到缓冲区:

id = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, image.getWidth(), image.getHeight(), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixels);

问题是贴图的颜色和原图颜色不一样!!

原图:

纹理图像:


这个答案 OpenGL Renders texture with different color than original image?, can't solve this issue, because GL_BGR is not valid in lwjgl Class GL11!

问题是红色和蓝色通道调换了。

在 OpenGL 中有可能使用 GL_BGR 格式,它指定了一种颜色通道交换的内部格式(与 GL_RGB 相比)。

OpenGL 4 Refpages - glTexImage2D
OpenGL Renders texture with different color than original image?.

在 OpenGL ES 中,您必须手动交换红色和蓝色通道,因为缺少内部格式 GL_BGR

OpenGL ES 3.0 Refpages - glTexImage2D
lwjgl - class GL11.

pixels = BufferUtils.createByteBuffer(bytePixels.length);
pixels.put(bytePixels);
pixels.flip();
for (int i = 0; i < pixels.length; i += 3) {
    byte t = pixels[i];
    pixels[i] = pixels[i+2];
    pixels[i+2] = t;
}

另一种可能性将在 OpenGL ES 3.0 或 OpenGL 扩展中给出 EXT_texture_swizzle:

从 OpenGL ES 3.0 开始,您可以使用纹理混合参数来交换颜色通道。见 glTexParameter:

GL_TEXTURE_SWIZZLE_R

Sets the swizzle that will be applied to the r component of a texel before it is returned to the shader. Valid values for param are GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_ZERO and GL_ONE. If GL_TEXTURE_SWIZZLE_R is GL_RED, the value for r will be taken from the first channel of the fetched texel. If GL_TEXTURE_SWIZZLE_R is GL_GREEN, the value for r will be taken from the second channel of the fetched texel. ...

这意味着在查找纹理时将交换颜色通道,方法是将以下纹理参数设置为纹理对象:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);


规范中的相关部分可以在 OpenGL ES 3.0.5 Specification; 3.8.14 Texture State; page 162

找到

要检查 OpenGL 扩展是否有效,可以使用 glGetString(GL_EXTENSIONS),其中 returns 支持扩展的 space 分隔列表。

参见 android bitmap pixel format for glTexImage2D