2015-12-15 5 views
8

Guten Tag!Android - OpenGL ES 2.0: Emulator (funktioniert) - Gerät (nicht)

Ich mache ein paar einfache Tests mit OpenGL ES 2.0 für Android. Ich verwende einen Modelllader, der im Emulator gut funktioniert. Wenn ich jedoch versuche, es auf einem ASUS ZenFone 2E (Android 5.0.1) (Prepaid-Telefon) zu verwenden, zeigt es einfach die klare Farbe des Hintergrunds ohne rotierendes Modell an. Ich hoffe, dass jemand, der sowohl OpenGL ES 2.0 als auch Android gut beherrscht, mir helfen wird. Sorry für die Ausführlichkeit, ich habe wirklich keine Ahnung, warum es nicht am Telefon funktioniert. Hier ist die Quelle (ich bin einen extremen Anfänger):

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; 
} 

Fragment Shader

uniform vec4 vColor; 

void main() { 
    gl_FragColor = vColor; 
} 

enter image description here

Antwort

1

Die Lösung für dieses besondere Problem:

Also, ich diese Linie meiner Fragment-Shader hinzugefügt:

precision mediump float;

geben Sie uns:

Fragment Shader

precision mediump float; 

uniform vec4 vColor; 

void main() { 
    gl_FragColor = vColor; 
} 

Warum dies funktioniert, ich Es ist mir peinlich zu sagen, dass ich es nicht weiß. Wenn jemand bereit ist weiter zu arbeiten, bin ich bitte neugierig. Ich lerne immer noch OpenGL ES 2.0. Beim Lesen des OpenGL ES 2.0 Programmierhandbuchs (Good Book) stieß ich auf diese Zeile. Und sie stellten fest: "In OpenGL ES 2.0 kann nichts gezeichnet werden, bis ein gültiger Vertex- und Fragment-Shader geladen wurde.. "Die Android-Tutorial auch diese Zeile enthalten, so dass ich weiß, dass es entscheidend ist

+0

Weitere Diskussion über Shadern und Beleuchtung in Android, versuchen, dieses Buch zu: https://pragprog.com/book/kbogla/opengl-es-2 -für-android - Ich studiere es gerade und die (downloadbar als zip) Samples sind ziemlich genial und alle funktionieren gut. –