我正在尝试使用opengl ES 2.0创建纹理图集。我想在一个大图像中绑定许多小图像。它在模拟器中运行良好,但它不适用于该设备。 这是我的代码:
gl.glGenTextures(1, textureID, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.block);
ByteBuffer pixels = ByteBuffer.allocate(bitmap.getWidth() * bitmap.getHeight() * 4);
bitmap.copyPixelsToBuffer(pixels);
gl.glTexSubImage2D(GL10.GL_TEXTURE_2D, 0, 0, 0, bitmap.getWidth(), bitmap.getHeight(), GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixels);
第一个Bitmap(bmp)是256x256红色图像,seconde Bitmap(位图)是16x16白色图像。在模拟器中,我看到一个带有一点白色图像的红色矩形,但是使用该设备我只能看到一个大的红色矩形。
答案 0 :(得分:1)
你正在使用2次幂纹理,这很棒,因为大多数OpenGL ES 2.0实现都不支持 npot 纹理。现在,因为您能够在模拟器上看到纹理,所以您似乎没有使用投影矩阵( MVP 矩阵)变换对象(要渲染)。此示例显示了如何执行此操作 -
public class GLES20Renderer implements Renderer {
private int _planeProgram;
private int _planeAPositionLocation;
private int _planeACoordinateLocation;
private int _planeUMVPLocation;
private int _planeUSamplerLocation;
private FloatBuffer _planeVFB;
private FloatBuffer _planeTFB;
private ShortBuffer _planeISB;
private float[] _ViewMatrix = new float[16];
private float[] _ProjectionMatrix = new float[16];
private float[] _MVPMatrix = new float[16];
private int _textureId;
public Context _context;
public GLES20Renderer(Context context) {
_context = context;
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
initplane();
float ratio = (float) width / height;
float zNear = 0.1f;
float zFar = 1000;
float fov = 0.95f; // 0.2 to 1.0
float size = (float) (zNear * Math.tan(fov / 2));
Matrix.setLookAtM(_ViewMatrix, 0, 0, 0, 50, 0, 0, 0, 0, 1, 0);
Matrix.frustumM(_ProjectionMatrix, 0, -size, size, -size / ratio, size / ratio, zNear, zFar);
_planeProgram = loadProgram(_planeVertexShaderCode, _planeFragmentShaderCode);
_planeAPositionLocation = GLES20.glGetAttribLocation(_planeProgram, "aPosition");
_planeACoordinateLocation = GLES20.glGetAttribLocation(_planeProgram, "aCoord");
_planeUMVPLocation = GLES20.glGetUniformLocation(_planeProgram, "uMVP");
_planeUSamplerLocation = GLES20.glGetUniformLocation(_planeProgram, "uSampler");
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
_textureId = textures[0];
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureId);
InputStream is1 = _context.getResources().openRawResource(R.drawable.brick);
Bitmap img1;
try {
img1 = BitmapFactory.decodeStream(is1);
} finally {
try {
is1.close();
} catch(IOException e) {
//e.printStackTrace();
}
}
GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); // GL_LINEAR
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img1, 0);
}
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Matrix.multiplyMM(_MVPMatrix, 0, _ProjectionMatrix, 0, _ViewMatrix, 0);
GLES20.glUseProgram(_planeProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _textureId);
GLES20.glUniform1i(_planeUSamplerLocation, 0);
GLES20.glUniformMatrix4fv(_planeUMVPLocation, 1, false, _MVPMatrix, 0);
GLES20.glVertexAttribPointer(_planeAPositionLocation, 3, GLES20.GL_FLOAT, false, 12, _planeVFB);
GLES20.glEnableVertexAttribArray(_planeAPositionLocation);
GLES20.glVertexAttribPointer(_planeACoordinateLocation, 2, GLES20.GL_FLOAT, false, 8, _planeTFB);
GLES20.glEnableVertexAttribArray(_planeACoordinateLocation);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, _planeISB);
System.gc();
}
public static void setZAngle(float angle) {
GLES20Renderer._zAngle = angle;
}
public static float getZAngle() {
return GLES20Renderer._zAngle;
}
private void initplane() {
float[] planeVFA = {
10.000000f,-10.000000f,0.000000f,
-10.000000f,-10.000000f,0.000000f,
10.000000f,10.000000f,0.000000f,
-10.000000f,10.000000f,0.000000f,
};
float[] planeTFA = {
// 1,0, 0,0, 1,1, 0,1
1,1, 0,1, 1,0, 0,0
};
short[] planeISA = {
2,3,1,
0,2,1,
};
ByteBuffer planeVBB = ByteBuffer.allocateDirect(planeVFA.length * 4);
planeVBB.order(ByteOrder.nativeOrder());
_planeVFB = planeVBB.asFloatBuffer();
_planeVFB.put(planeVFA);
_planeVFB.position(0);
ByteBuffer planeTBB = ByteBuffer.allocateDirect(planeTFA.length * 4);
planeTBB.order(ByteOrder.nativeOrder());
_planeTFB = planeTBB.asFloatBuffer();
_planeTFB.put(planeTFA);
_planeTFB.position(0);
ByteBuffer planeIBB = ByteBuffer.allocateDirect(planeISA.length * 2);
planeIBB.order(ByteOrder.nativeOrder());
_planeISB = planeIBB.asShortBuffer();
_planeISB.put(planeISA);
_planeISB.position(0);
}
private int loadShader(int type, String source) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
return shader;
}
private int loadProgram(String vertexShaderCode, String fragmentShaderCode) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
int program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
return program;
}
private final String _planeVertexShaderCode =
"attribute vec4 aPosition; \n"
+ "attribute vec2 aCoord; \n"
+ "varying vec2 vCoord; \n"
+ "uniform mat4 uMVP; \n"
+ "void main() { \n"
+ " gl_Position = uMVP * aPosition; \n"
+ " vCoord = aCoord; \n"
+ "} \n";
private final String _planeFragmentShaderCode =
"#ifdef GL_FRAGMENT_PRECISION_HIGH \n"
+ "precision highp float; \n"
+ "#else \n"
+ "precision mediump float; \n"
+ "#endif \n"
+ "varying vec2 vCoord; \n"
+ "uniform sampler2D uSampler; \n"
+ "void main() { \n"
+ " gl_FragColor = texture2D(uSampler,vCoord); \n"
+ "} \n";
}
更多这些内容 - http://www.apress.com/9781430250531
答案 1 :(得分:0)
如果您的代码实际上是OpenGL ES 2.0,则不应使用GL10包装类。我认为1.0不支持2种纹理大小的非功能,不使用扩展,但我想你已经处理了?您可能在设备的OpenGL ES驱动程序中发现了一个错误,因为它可以在AVD仿真器上运行。尝试使用不同类型GPU的其他设备。本文将有所帮助: