我尝试在正方形上渲染一个简单的纹理 .png,但它始终显示为黑色。 在我的示例代码中,渲染了 2 个正方形,其中一个带有纹理 wall.png,第二个带有用于测试的 4 像素字节缓冲区。 我检查了位图的一些像素和大小,它们都没有问题。 4 像素字节缓冲区正在工作,但出现奇怪的故障。 字节缓冲区需要 2 个额外字节的数据,我不知道是什么原因导致的。
感谢您的帮助!
package com.example.opengles3_test1;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class Renderer_Texture implements GLSurfaceView.Renderer {
private static String TAG = "Renderer"; //For LOG
final int VERTEX_POS_SIZE = 3; // x, y and z
final int VERTEX_COLOR_SIZE = 4; // r, g, b, and a
final int VERTEX_TEXTUR_SIZE=2; //x,y
final int VERTEX_POS_INDX = 0;
final int VERTEX_COLOR_INDX = 1;
final int VERTEX_TEXTUR_INDX = 2;
final int VERTEX_STRIDE = (4 * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE+VERTEX_TEXTUR_SIZE));
// 3 vertices, with (x,y,z) ,(r, g, b, a), (x,y) per-vertex
final int[] textures = new int[2];
private final float[] mVerticesData =
{
// positions // colors // texture coords
-0.1f, 0.4f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top right
-0.1f, -0.4f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom right
-0.8f, -0.4f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.8f, 0.4f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f // top left
};
private final float[] mVerticesData2 =
{
// positions // colors // texture coords
0.8f, 0.4f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top right
0.8f, -0.4f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom right
0.1f, -0.4f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, // bottom left
0.1f, 0.4f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f // top left
};
private final short[] mIndicesData =
{
0, 1, 3 , 1, 2, 3
};
ShaderV1 Shaderprog1;
private int[] VBOIds = new int[4]; // VertexBufferObject Ids
private int[] VAOId = new int[2]; // VertexArrayObject Id
private int mWidth;
private int mHeight;
private FloatBuffer mVertices;
private ShortBuffer mIndices;
private FloatBuffer mVertices2;
public Renderer_Texture(Context context) {
mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mVertices.put(mVerticesData).position(0);
mVertices2 = ByteBuffer.allocateDirect(mVerticesData2.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mVertices2.put(mVerticesData2).position(0);
mIndices = ByteBuffer.allocateDirect(mIndicesData.length * 2)
.order(ByteOrder.nativeOrder()).asShortBuffer();
mIndices.put(mIndicesData).position(0);
}
private static Bitmap convertBitmapToConfig(Bitmap bitmap, Bitmap.Config config) {
if (bitmap.getConfig() == config) {
return bitmap;
}
Bitmap result = bitmap.copy(config, false);
bitmap.recycle();
return result;
}
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
Shaderprog1= new ShaderV1("res/raw/vertext_shader1.vs", "res/raw/fragment_shader1.fs");
GLES30.glGenBuffers(4, VBOIds, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOIds[0]);
mVertices.position(0);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mVerticesData.length * 4,
mVertices, GLES30.GL_STATIC_DRAW);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, VBOIds[1]);
mIndices.position(0);
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, 2 * mIndicesData.length,
mIndices, GLES30.GL_STATIC_DRAW);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOIds[2]);
mVertices2.position(0);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, mVerticesData2.length * 4,
mVertices2, GLES30.GL_STATIC_DRAW);
GLES30.glGenVertexArrays(2, VAOId, 0);
GLES30.glBindVertexArray(VAOId[0]);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOIds[0]);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, VBOIds[1]);
GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);
GLES30.glEnableVertexAttribArray(VERTEX_COLOR_INDX);
GLES30.glEnableVertexAttribArray(VERTEX_TEXTUR_INDX);
GLES30.glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,
GLES30.GL_FLOAT, false, VERTEX_STRIDE,
0);
GLES30.glVertexAttribPointer(VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE,
GLES30.GL_FLOAT, false, VERTEX_STRIDE,
(VERTEX_POS_SIZE * 4));
GLES30.glVertexAttribPointer(VERTEX_TEXTUR_INDX, VERTEX_TEXTUR_SIZE,
GLES30.GL_FLOAT, false, VERTEX_STRIDE,
(VERTEX_POS_SIZE * 4+VERTEX_COLOR_SIZE*4));
//second:
GLES30.glBindVertexArray(VAOId[1]);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBOIds[2]);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, VBOIds[1]);
GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);
GLES30.glEnableVertexAttribArray(VERTEX_COLOR_INDX);
GLES30.glEnableVertexAttribArray(VERTEX_TEXTUR_INDX);
GLES30.glVertexAttribPointer(VERTEX_POS_INDX, VERTEX_POS_SIZE,
GLES30.GL_FLOAT, false, VERTEX_STRIDE,
0);
GLES30.glVertexAttribPointer(VERTEX_COLOR_INDX, VERTEX_COLOR_SIZE,
GLES30.GL_FLOAT, false, VERTEX_STRIDE,
(VERTEX_POS_SIZE * 4));
GLES30.glVertexAttribPointer(VERTEX_TEXTUR_INDX, VERTEX_TEXTUR_SIZE,
GLES30.GL_FLOAT, false, VERTEX_STRIDE,
(VERTEX_POS_SIZE * 4+VERTEX_COLOR_SIZE*4));
// Reset to the default VAO
GLES30.glBindVertexArray(0);
GLES30.glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
GLES30.glGenTextures(2, textures,0);
if (textures[0] == 0) {
Log.e(TAG,"could not bind texture");
return;
}
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0]);
// set the texture wrapping parameters
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
// set texture filtering parameters
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
Bitmap bitmap = null;
try {
bitmap =convertBitmapToConfig(BitmapFactory.decodeStream(ShaderV1.class.getClassLoader().getResourceAsStream("res/raw/wall.jpg")), Bitmap.Config.ARGB_8888);
ByteBuffer buffer = ByteBuffer.allocateDirect(bitmap.getByteCount());
bitmap.copyPixelsToBuffer(buffer);
buffer.rewind();
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0]);
GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D,0, GLES30.GL_RGB, bitmap.getWidth(), bitmap.getHeight(), 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, buffer);
//Log.e(TAG,"pixel "+ String.format("#%06X", (0xFFFFFF & bitmap.getPixel(200,200)))); //looks correct
//Log.d(TAG,"bitmapsize:" + bitmap.getWidth() +" " + bitmap.getHeight()); //looks correct
GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);
} catch (Exception e) {
Log.e(TAG,"texture error "+ e.getLocalizedMessage());
} finally {
if (bitmap != null) {
bitmap.recycle();
}
}
byte[] bytes = {
// R G B
(byte) 0xcf,(byte) 0x00,(byte) 0x00, //EDGE 1
(byte) 0x8f,(byte) 0x00,(byte) 0x50,(byte) 0x00,(byte) 0x00, //EDGE 2 WTF 2 extra?!?
(byte) 0x5f,(byte) 0x80,(byte) 0x00, //EDGE 3
(byte) 0x3f,(byte) 0x00,(byte) 0x80}; //EDGE 4
ByteBuffer b = ByteBuffer.wrap(bytes);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[1]);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE); //GLES30.GL_REPEAT also work
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE); //GLES30.GL_REPEAT also work
// set texture filtering parameters
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
GLES30.glTexImage2D ( GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGB, 2, 2, 0, GLES30.GL_RGB, GLES30.GL_UNSIGNED_BYTE, b );
GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);
Shaderprog1.use();
GLES30.glUniform1i(GLES30.glGetUniformLocation(Shaderprog1.getID(), "texture1"), 0);
}
public void onDrawFrame(GL10 glUnused) {
GLES30.glViewport(0, 0, mWidth, mHeight);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[1]);
Shaderprog1.use();
GLES30.glBindVertexArray(VAOId[0]);
GLES30.glDrawElements(GLES30.GL_TRIANGLES, mIndicesData.length, GLES30.GL_UNSIGNED_SHORT, 0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textures[0]);
GLES30.glBindVertexArray(VAOId[1]);
GLES30.glDrawElements(GLES30.GL_TRIANGLES, mIndicesData.length, GLES30.GL_UNSIGNED_SHORT, 0);
GLES30.glBindVertexArray(0);
}
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
mWidth = width;
mHeight = height;
Log.d ( TAG, width +" "+ height );
}
}
Android 提供了简单的 API 用于将位图加载为 OpenGL 纹理:
GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);
编辑:您可以在这里找到更多相关信息https://developer.android.com/reference/android/opengl/GLUtils#texImage2D(int,%20int,%20android.graphics.Bitmap,%20int)