【问题标题】:Why do the textured image colors are not the same as the origin?为什么纹理图像颜色与原点不同?
【发布时间】:2018-08-25 14:57:37
【问题描述】:

我正在使用 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?的回答,不能解决这个问题,因为GL_BGRlwjgl Class GL11中无效!

【问题讨论】:

  • “问题是,纹理图像的颜色不是原始图像?” - 有什么区别?
  • @Rabbid76 不同之处如上图所示!!
  • 问题是红色和蓝色通道交换了。这是 OpenGL 还是 OpenGL ES?您使用哪个 OpenGL 版本?
  • 您的图片很可能是BGR 格式。只需在glTexImage2D() 呼叫中尝试GL11.GL_BGR
  • @Jaa 不,在这个版本的 OpenGL 中没有GL_BGR 格式。见Class GL11

标签: java c++ opengl lwjgl


【解决方案1】:

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

在 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

设置将在纹理元素的 r 组件返回到着色器之前应用到它的 swizzle。参数的有效值为GL_REDGL_GREENGL_BLUEGL_ALPHAGL_ZEROGL_ONE。如果GL_TEXTURE_SWIZZLE_RGL_RED,r 的值将从获取的纹素的第一个通道中获取。如果GL_TEXTURE_SWIZZLE_RGL_GREEN,r 的值将从获取的纹素的第二个通道中获取。 ...

这意味着当查找纹理时颜色通道将被交换,通过将以下纹理参数设置到纹理对象:

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),它返回一个以空格分隔的支持扩展列表。

参见android bitmap pixel format for glTexImage2D

【讨论】:

  • 感谢您的回答。因为我使用“LWJGL”,我既没有找到 GL_BGR 格式也没有找到 GL_TEXTURE_SWIZZLE 所以我用你的交换代码在红色和蓝色之间交换。非常感谢..
猜你喜欢
  • 2011-05-04
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
  • 1970-01-01
  • 2019-01-17
  • 2023-03-22
相关资源
最近更新 更多