为什么纹理图像颜色与原点不同?
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。
我正在使用 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
andGL_ONE
. IfGL_TEXTURE_SWIZZLE_R
isGL_RED
, the value for r will be taken from the first channel of the fetched texel. IfGL_TEXTURE_SWIZZLE_R
isGL_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。