美好的一天!
我正在使用OpenGL ES 2.0 for Android做一些简单的测试.我正在使用一个在模拟器中运行良好的模型加载器.但是,当我尝试在华硕ZenFone 2E(Android 5.0.1)(预付费电话)上使用它时,它只显示背景的清晰颜色而没有旋转模型.我希望那些在OpenGL ES 2.0和Android方面都有丰富经验的人会帮助我.对不起,我真的不知道为什么它没有在手机上工作.这是源(我是一个极端的新手):
GameView.java:
package wise.child.dials; import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.Matrix; import android.os.SystemClock; import java.io.IOException; import java.nio.FloatBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import model.Model; import render.Program; import render.Shader; import util.OBJLoader; public class GameView extends GLSurfaceView implements GLSurfaceView.Renderer { // App Context private Context mContext; // Handles private int mPositionHandle; private int mColorHandle; private int mMVPMatrixHandle; // Program & Shaders private Program testProgram; private Shader testVertexShader; private Shader testFragmentShader; // Model private Model model; private FloatBuffer vertexFloatBuffer; private int vertexCount; // Matrices private final float[] mMVPMatrix = new float[16]; private final float[] mProjectionMatrix = new float[16]; private final float[] mViewMatrix = new float[16]; private float[] mRotationMatrix = new float[16]; // Constructor public GameView(Context context) { super(context); // App Context mContext = context; // OpenGL ES 2.0 Context setEGLContextClientVersion(2); // Renderer setRenderer(this); } /*-------------------*/ /* Rendering Methods */ /*-------------------*/ // One Time Initialization @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { GLES20.glClearColor(0.95f, 0.95f, 0.95f, 1f); // Initialize Shaders testVertexShader = new Shader(GLES20.GL_VERTEX_SHADER, mContext, R.raw.test_vertex_shader); testFragmentShader = new Shader(GLES20.GL_FRAGMENT_SHADER, mContext, R.raw.test_fragment_shader); // Create Program testProgram = new Program(testVertexShader, testFragmentShader); testProgram.use(); // Get Handles - Uniforms & Attributes mPositionHandle = testProgram.getAttribute("vPosition"); mColorHandle = testProgram.getUniform("vColor"); mMVPMatrixHandle = testProgram.getUniform("uMVPMatrix"); // Model try { model = OBJLoader.loadOBJ(mContext, R.raw.spider); vertexFloatBuffer = model.getVerticesFromIndices(); vertexCount = model.getVertexCount(); } catch (IOException e) { e.printStackTrace(); } } // Drawing Call @Override public void onDrawFrame(GL10 gl) { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // Time and Rotation Animation float[] scratch = new float[16]; long time = SystemClock.uptimeMillis() % 4000L; float angle = 0.090f * ((int) time); Matrix.setRotateM(mRotationMatrix, 0, angle, angle, angle, angle); // Set and Bind Data GLES20.glEnableVertexAttribArray(mPositionHandle); GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 12, vertexFloatBuffer); // Set Color float[] color = {.75f, 0f, 0f, 1f}; GLES20.glUniform4fv(mColorHandle, 1, color, 0); // Camera Position - View Matrix Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -15, 0f, 0f, 0f, 0f, 1.0f, 0.0f); // Projection x View Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); // Rotation x MVP Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); // Final Matrix GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, scratch, 0); // Draw GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); // Disable GLES20.glDisableVertexAttribArray(mPositionHandle); } // GLSurface Changed @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // GL Viewport & Aspect Ratio GLES20.glViewport(0, 0, width, height); float aspectRatio = (float) width / height; // Calculate Projection Matrix.frustumM(mProjectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1, 3, 50); } }
Shader.java
package render; import android.content.Context; import android.opengl.GLES20; import android.util.Log; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Shader { // Shader Source Code public String shaderSource; // Shader Handle public int shaderHandle; public int programHandle; public Shader(int type, Context context, int resID) { try { shaderSource = loadShader(context, resID); Log.d("Shader Load", "Success!"); System.out.println(shaderSource); } catch (IOException e) { Log.d("Shader Load", "Failed."); e.printStackTrace(); } shaderHandle = GLES20.glCreateShader(type); GLES20.glShaderSource(shaderHandle, shaderSource); GLES20.glCompileShader(shaderHandle); } // Get From Raw Folder private String loadShader(Context context, int resID) throws IOException { BufferedReader reader = new BufferedReader( new InputStreamReader(context.getResources().openRawResource(resID)) ); String line, shader; StringBuilder builder = new StringBuilder(); while ((line = reader.readLine()) != null) { builder.append(line).append('\n'); } reader.close(); shader = builder.toString(); return shader; } // Associated Program public void setProgram(int handle) { programHandle = handle; } }
Program.java
package render; import android.opengl.GLES20; import java.util.ArrayList; import java.util.List; public class Program { public int handle; private Shader vertexShader; private Shader fragmentShader; private Listattributes = new ArrayList (); private List uniforms = new ArrayList (); public Program(Shader vertexShader, Shader fragmentShader) { this.vertexShader = vertexShader; this.fragmentShader = fragmentShader; this.vertexShader.setProgram(handle); this.fragmentShader.setProgram(handle); handle = GLES20.glCreateProgram(); GLES20.glAttachShader(handle, vertexShader.shaderHandle); GLES20.glAttachShader(handle, fragmentShader.shaderHandle); GLES20.glLinkProgram(handle); } public void use() { GLES20.glUseProgram(handle); } public int getAttribute(String name) { return GLES20.glGetAttribLocation(handle, name); } public void setAttribute(String name) { } public int getUniform(String name) { return GLES20.glGetUniformLocation(handle, name); } }
Model.java
package model; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.List; public class Model { private static final int NUM_OF_COORDS = 3; public Listvertices = new ArrayList (); public List normals = new ArrayList (); public List faces = new ArrayList (); public Model() {} public int getVertexCount() { return faces.size() * NUM_OF_COORDS; } public FloatBuffer getVerticesFromIndices() { int numOfVertices = 3; int bytesPerFloat = 4; ByteBuffer bb = ByteBuffer.allocateDirect(faces.size() * numOfVertices * NUM_OF_COORDS * bytesPerFloat); bb.order(ByteOrder.nativeOrder()); FloatBuffer vertexFloatBuffer = bb.asFloatBuffer(); // Use indices to find proper vertex for (Face face : faces) { // VERTEX 1 vertexFloatBuffer.put(vertices.get((int) (face.vertex.x - 1)).x); vertexFloatBuffer.put(vertices.get((int) (face.vertex.x - 1)).y); vertexFloatBuffer.put(vertices.get((int)(face.vertex.x - 1)).z); // VERTEX 2 vertexFloatBuffer.put(vertices.get((int)(face.vertex.y - 1)).x); vertexFloatBuffer.put(vertices.get((int)(face.vertex.y - 1)).y); vertexFloatBuffer.put(vertices.get((int)(face.vertex.y - 1)).z); // VERTEX 3 vertexFloatBuffer.put(vertices.get((int)(face.vertex.z - 1)).x); vertexFloatBuffer.put(vertices.get((int)(face.vertex.z - 1)).y); vertexFloatBuffer.put(vertices.get((int)(face.vertex.z - 1)).z); } vertexFloatBuffer.position(0); return vertexFloatBuffer; } public FloatBuffer getNormalsFromIndices() { int numOfVertices = 3; int bytesPerFloat = 4; ByteBuffer bb = ByteBuffer.allocateDirect(faces.size() * numOfVertices * NUM_OF_COORDS * bytesPerFloat); bb.order(ByteOrder.nativeOrder()); FloatBuffer normalFloatBuffer = bb.asFloatBuffer(); // Use indices to find proper normal for (Face face : faces) { // VERTEX 1 normalFloatBuffer.put(normals.get((int) (face.normal.x - 1)).x); normalFloatBuffer.put(normals.get((int) (face.normal.x - 1)).y); normalFloatBuffer.put(normals.get((int)(face.normal.x - 1)).z); // VERTEX 2 normalFloatBuffer.put(normals.get((int)(face.normal.y - 1)).x); normalFloatBuffer.put(normals.get((int)(face.normal.y - 1)).y); normalFloatBuffer.put(normals.get((int)(face.normal.y - 1)).z); // VERTEX 3 normalFloatBuffer.put(normals.get((int)(face.normal.z - 1)).x); normalFloatBuffer.put(normals.get((int)(face.normal.z - 1)).y); normalFloatBuffer.put(normals.get((int)(face.normal.z - 1)).z); } normalFloatBuffer.position(0); return normalFloatBuffer; } }
OBJLoader.java
package util; import android.content.Context; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import model.Face; import model.Model; import model.Vertex; public class OBJLoader { /* loads .obj data from file in res/raw folder */ public static Model loadOBJ(Context context, int resID) throws IOException { Model model = new Model(); BufferedReader reader = new BufferedReader( new InputStreamReader(context.getResources().openRawResource(resID)) ); String line; while ((line = reader.readLine()) != null) { if (line.startsWith("v ")) { // Vertex float x = Float.valueOf(line.split(" ")[1]); float y = Float.valueOf(line.split(" ")[2]); float z = Float.valueOf(line.split(" ")[3]); model.vertices.add(new Vertex(x, y, z)); } else if (line.startsWith("vn ")) { // Normal float x = Float.valueOf(line.split(" ")[1]); float y = Float.valueOf(line.split(" ")[2]); float z = Float.valueOf(line.split(" ")[3]); model.normals.add(new Vertex(x, y, z)); } else if (line.startsWith("f ")) { // Face Vertex vertexIndices = new Vertex( Float.valueOf(line.split(" ")[1].split("/")[0]), Float.valueOf(line.split(" ")[2].split("/")[0]), Float.valueOf(line.split(" ")[3].split("/")[0]) ); Vertex normalIndices = new Vertex( Float.valueOf(line.split(" ")[1].split("/")[2]), Float.valueOf(line.split(" ")[2].split("/")[2]), Float.valueOf(line.split(" ")[3].split("/")[2]) ); model.faces.add(new Face(vertexIndices, normalIndices)); } } reader.close(); return model; } }
MainActivity.java
package wise.child.dials; import android.app.Activity; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Fullscreen & No Title Bar requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); // Set OpenGL ES Drawing Surface (Game View) setContentView(new GameView(this)); } }
AndroidManifest.xml中
顶点着色器
attribute vec4 vPosition; uniform mat4 uMVPMatrix; void main() { gl_Position = uMVPMatrix * vPosition; }
片段着色器
uniform vec4 vColor; void main() { gl_FragColor = vColor; }