Shi*_*gon 5 opengl textures colors jogl
我制作了一个简单的程序来创建一个Ortho透视图,然后在四边形上放置一个包含png的纹理但是,我无法弄清楚为什么有些颜色会显示为混乱.
png看起来像这样(中间的白色矩形是透明的):

我的OpenGL程序中的四边形如下所示:

下面是初始化OpenGL的代码以及OpenGL线程调用的方法中的内容.我正在使用JOGL.
public void init(GLAutoDrawable gLDrawable) {
gl.glGenTextures(1, textureId, 0);
gl.glBindTexture(GL2.GL_TEXTURE_2D, textureId[0]);
gl.glTexParameterf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
gl.glTexParameterf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
gl.glTexParameterf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_REPEAT);
gl.glTexParameterf(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_REPEAT);
BufferedImage image = null;
try {
image = ImageIO.read(new File("d:\\temp\\projects\\openglTest1\\texTest.png"));
} catch (IOException e1) {e1.printStackTrace();}
DataBufferByte dataBufferByte = (DataBufferByte) image.getRaster().getDataBuffer();
Buffer imageBuffer = ByteBuffer.wrap(dataBufferByte.getData());
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL2.GL_RGBA, image.getWidth(), image.getHeight(), 0, GL2.GL_RGBA, GL.GL_UNSIGNED_BYTE, imageBuffer);
gl.glEnable(GL2.GL_TEXTURE_2D);
gl.glBlendFunc(GL2.GL_ONE, GL2.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL2.GL_BLEND_SRC);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClearDepth(1.0f);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
}
//this is called by the OpenGL Thread
public void display(GLAutoDrawable gLDrawable) {
gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
gl.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
gl.glFrontFace(GL2.GL_CCW);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, textureBuffer);
gl.glDrawElements(GL.GL_TRIANGLES, indices.length, GL.GL_UNSIGNED_BYTE, indexBuffer);
gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
}
Run Code Online (Sandbox Code Playgroud)
这让我感到困惑,因为虽然我不是OpenGL专家,但我试图在使用它们之前了解上述所有OpenGL命令的作用.事实上,我在Android上不一样,所有内容都显示正常,但是当使用JOGL在Java中进行时,我得到了这里描述的结果.我唯一不同的是我加载png图像的方式.在Adroid上有一个这样的帮助方法:
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapStatic, 0);
Run Code Online (Sandbox Code Playgroud)
和JOGL一起,我正在通过以下方式进行自己的加载:
try {
image = ImageIO.read(new File("d:\\temp\\projects\\openglTest1\\texTest.png"));
} catch (IOException e1) {e1.printStackTrace();}
DataBufferByte dataBufferByte = (DataBufferByte) image.getRaster().getDataBuffer();
Buffer imageBuffer = ByteBuffer.wrap(dataBufferByte.getData());
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL2.GL_RGBA, image.getWidth(), image.getHeight(), 0, GL2.GL_RGBA, GL.GL_UNSIGNED_BYTE, imageBuffer);
Run Code Online (Sandbox Code Playgroud)
如上所述.
== ==更新
根据jcadam的评论,我尝试将像素数据的格式设置为GL_BGRA,如下所示:
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL2.GL_RGBA, image.getWidth(), image.getHeight(), 0, GL2.GL_BGRA, GL.GL_UNSIGNED_BYTE, imageBuffer);
Run Code Online (Sandbox Code Playgroud)
颜色仍然混乱,但这次是一个不同的混乱:

如何找出我的png图像的特定格式?
==更新2 - 解决方案实施==
好的,首先,我要感谢jcadam,rotoglup和Tim指出我正确的方向.
简而言之,问题在于Java在解码图像时对像素进行排序的方式并不总是传递给OpenGL的良好顺序.更确切地说,如果你的图像中没有Alpha通道,那么没关系,但如果你有一个alpha通道,那么订单就会很糟糕,而且有些颜色会混乱.
现在,我开始制作自己的手动实现,适用于32位PNG和24位JPEG:
public void texImage2D(File imageLocation,GL gl) {
BufferedImage initialImage = null;
try {
initialImage = ImageIO.read(imageLocation);
} catch (IOException e1) {
throw new RuntimeException(e1.getMessage(), e1);
}
int imgHeight = initialImage.getHeight(null);
int imgWidth = initialImage.getWidth(null);
ColorModel cm = initialImage.getColorModel();
boolean hasAlpha = cm.hasAlpha();
Buffer buffer = null;
int openGlInternalFormat = -1;
int openGlImageFormat = -1;
if(!hasAlpha) {
DataBufferByte dataBufferByte = (DataBufferByte) initialImage.getRaster().getDataBuffer();
buffer = ByteBuffer.wrap(dataBufferByte.getData());
openGlInternalFormat = GL2.GL_RGB;
openGlImageFormat = GL2.GL_BGR;
} else {
openGlInternalFormat = GL2.GL_RGBA;
openGlImageFormat = GL2.GL_RGBA;
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, imgWidth, imgHeight, 4, null);
ComponentColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] { 8, 8, 8, 8 },
true, false,
ComponentColorModel.TRANSLUCENT,
DataBuffer.TYPE_BYTE);
BufferedImage bufImg = new BufferedImage(colorModel,
raster, false,
null);
Graphics2D g = bufImg.createGraphics();
g.drawImage(initialImage, null, null);
DataBufferByte imgBuf = (DataBufferByte) raster.getDataBuffer();
byte[] bytes = imgBuf.getData();
buffer = ByteBuffer.wrap(bytes);
g.dispose();
}
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, openGlInternalFormat, imgWidth, imgHeight, 0, openGlImageFormat, GL.GL_UNSIGNED_BYTE, buffer);
}
Run Code Online (Sandbox Code Playgroud)
但后来我发现JOGL有自己的辅助工具,这实际上是我最终使用的:
//this code should be called in init(), to load the texture:
InputStream stream = new FileInputStream("d:\\temp\\projects\\openglTest1\\texTest.png");
TextureData data = TextureIO.newTextureData(gl.getGLProfile(),stream, false, "png");
Texture myTexture = TextureIO.newTexture(data);
//this code should be called in the draw/display method, before the vertices drawing call
myTexture.enable(gl);
myTexture.bind(gl);
Run Code Online (Sandbox Code Playgroud)
对我来说它看起来像ABGR.如果你只看颜色:
png red (A1,B0,G0,R1) looks like
opengl red (R1,G0,B0,A1)
png bluegreen (A1, B1, G1, R0) looks like
opengl white (R1, G1, B1, A0)
png blue (A1, B1, G0, R0) looks like
opengl yellow (R1, G1, B0, A0)
png clear (A0, B?, G?, R?) could be
ogl bluegreen (R0, B?, G?, A?)
Run Code Online (Sandbox Code Playgroud)
如果禁用了opengl透明度,则alpha通道无关紧要.