studio programacion herramientas fundamentos con avanzado aplicaciones java android opengl-es opengl-es-2.0

java - programacion - Android-OpenGL ES 2.0: Emulador(funciona)-Dispositivo(no)



manual de android en pdf (1)

La solución a este problema particular:

Entonces, agregué esta línea a mi sombreador de fragmentos:

precision mediump float;

Para darnos:

Fragmento Shader

precision mediump float; uniform vec4 vColor; void main() { gl_FragColor = vColor; }

Por qué funcionó esto, me avergüenza decir que no sé. Si alguien está dispuesto a dar más detalles, por favor, tengo curiosidad. Todavía estoy aprendiendo OpenGL ES 2.0. En mi lectura de OpenGL ES 2.0 Programming Guide ( Good Book ), encontré esa línea. Y señalaron: "En OpenGL ES 2.0, no se puede dibujar nada a menos que se haya cargado un vértice y un sombreador de fragmentos válidos". El tutorial de Android también incluyó esta línea, así que sé que es crítico.

¡Buen día!

Estoy haciendo algunas pruebas simples con OpenGL ES 2.0 para Android. Estoy usando un cargador de modelos que funciona bien en el emulador. Sin embargo, cuando intento usarlo en un ASUS ZenFone 2E (Android 5.0.1) (teléfono prepago) simplemente muestra el color claro del fondo sin modelo giratorio. Espero que alguien que tenga mucha experiencia en OpenGL ES 2.0 y Android me ayude. Perdón por la verborrea, realmente no tengo idea de por qué no funciona en el teléfono. Aquí está la fuente (soy un novato extremo):

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 List<String> attributes = new ArrayList<String>(); private List<String> uniforms = new ArrayList<String>(); 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 List<Vertex> vertices = new ArrayList<Vertex>(); public List<Vertex> normals = new ArrayList<Vertex>(); public List<Face> faces = new ArrayList<Face>(); 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

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="wise.child.dials"> <uses-feature android:glEsVersion="0x00020000" android:required="true" /> <supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" /> <supports-gl-texture android:name="GL_OES_compressed_paletted_texture" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MenuActivity" android:screenOrientation="landscape" android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen"> </activity> <activity android:name=".MainActivity" android:screenOrientation="landscape" android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SplashScreen" /> </application> </manifest>

Vertex Shader

attribute vec4 vPosition; uniform mat4 uMVPMatrix; void main() { gl_Position = uMVPMatrix * vPosition; }

Fragmento Shader

uniform vec4 vColor; void main() { gl_FragColor = vColor; }