2013-07-01 14 views
10

Ich habe ein sehr schweres Problem, ein Shader-Programm auf Android zu erstellen. wenn ich glCreateShader oder glCreateProgram rufen jeder gibt immer 0 zurückGlCreateShader und GlCreateProgram fail on Android

ich alle meine Basen in Bezug auf die Fehlersuche durchgeführt haben:

  • ich sicherstellen, überprüfte ich einen ogl Zusammenhang hatte (ich weiß, getestet i dies durch Löschen des Framebuffers mit verschiedenen Farben, die funktionierten).

  • Ich versuchte glGetError aber es gab nichts zurück (GL_NO_ERROR)

Ich bin kein opengl oder Android-Experten, damit ich von irgend etwas wissen nicht anderes, dass dies verursacht werden könnte.

Ich habe meine App auf einem Nexus 7 Tablet ausgeführt und ich verwende OpenGL ES 2.0, und ich ziele auf die neueste Version von Android (Version 17).

Schließlich habe ich meinen Code als auch zu zeigen:

Hier ist mein Standardcode ist, dass die App einrichtet:

public class Platform implements ILinkable<Activity> { 
    class GameLoop extends GLSurfaceView implements GLSurfaceView.Renderer { 
     class Graphics2D implements IGraphics2D { 
      int width = 0; 
      int height = 0; 

      public void setWidth (int width) { this.width = width; } 
      public void setHeight(int height) { this.height = height; } 

      public int getWidth() { return width; } 
      public int getHeight() { return height; } 
     } 

     class Time implements ITime { 
      float frametime = 0; 
      float totaltime = 0; 
      long temptime = 0; 
      boolean running = true; 

      public void beginTimeCount() { 
       temptime = System.nanoTime(); 
      } 

      public void endTimeCount() { 
       frametime = (System.nanoTime() - temptime)/1000000; 
       totaltime += frametime; 
      } 

      public float getFrameTime() { return frametime; } 
      public float getTotalTime() { return totaltime; } 
     } 

     Graphics2D graphics2d = new Graphics2D(); 
     Time  time  = new Time(); 
     boolean running = true; 

     public GameLoop(Context context) { 
      super(context); 

      setEGLContextClientVersion(2); 
      setRenderer(this); 
      //setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 
     } 

     public void onSurfaceCreated(GL10 unused, EGLConfig config) { 
      GLES20.glClearColor(0.5f, 0.0f, 0.5f, 1.0f); 
     } 

     public void onDrawFrame(GL10 unused) { 
      if (running) { 
       time.beginTimeCount(); 

       for (IUpdateable u : Platform.this.root.update) 
        u.onUpdate(time); 

       GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 
       for (IDrawable2D d : Platform.this.root.draw2d) { 
        d.onDraw2D(graphics2d); 
       } 

       for (IDrawable3D d : Platform.this.root.draw3d) 
        d.onDraw3D(); 

       time.endTimeCount(); 
      } 
     } 

     public void onSurfaceChanged(GL10 unused, int width, int height) { 
      GLES20.glViewport(0,0, width, height); 
      graphics2d.setWidth(width); 
      graphics2d.setHeight(height); 
      for (IDrawable2D d : Platform.this.root.draw2d) 
       d.onSize2D(graphics2d); 
     } 

     public void onPause() { 
      super.onPause(); 
      running = false; 
     } 

     public void onResume() { 
      super.onResume(); 
      running = true; 
     } 
    } 

    private GameLoop gameloop; 
    public Node root; 

    public Platform() { 
     this.root = new Node(); 
    } 

    public void link(Activity activity) { 
     this.gameloop = new GameLoop(activity); 
     activity.requestWindowFeature(Window.FEATURE_NO_TITLE); 
     activity.setContentView(this.gameloop); 
    } 

    public void unlink(Activity activity) { 
     this.gameloop = null; 
     activity.setContentView(null); 
    } 
} 

und das ist die Haupttätigkeit:

public class MainActivity extends Activity { 

    private Game game; 
    private Platform platform; 

    public MainActivity() { 
     platform = new Platform(); 
     game = new Game(); 
    } 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     platform.link(this); 
     game.link(platform.root); 
     game.onStart(); 
    } 

    public void onDestroy() { 
     super.onDestroy(); 
     game.onStop(); 
     game.unlink(platform.root); 
     platform.unlink(this); 
    } 
} 

und dies ist der Code, der die Shader und das Programm erstellt:

public static int loadShader(int shaderType, String source) throws FmtException { 
    int[] gotVar = new int[]{ 0 }; 
    int shader = GLES20.glCreateShader(shaderType); 

    if (shader == 0) 
     throw new FmtException(FmtException.GLES,"could not create shader: %s",getError()); 

    GLES20.glShaderSource(shader, source); 
    GLES20.glCompileShader(shader); 

    GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, gotVar, 0); 
    if (gotVar[0] == 0) { 
     GLES20.glGetShaderiv(shader, GLES20.GL_INFO_LOG_LENGTH, gotVar, 0); 
     if (gotVar[0] != 0) { 
      GLES20.glDeleteShader(shader); 
      throw new FmtException(FmtException.GLES, "could not compile shader %d:\n%s\n",shaderType, GLES20.glGetShaderInfoLog(shader)); 
     } 
    } 

    return shader; 
} 

public static int createProgram(String pVertexSource, String pFragmentSource) throws FmtException { 
    int[] gotVar = new int[]{ GLES20.GL_FALSE }; 
    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, pVertexSource); 
    int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, pFragmentSource); 

    int program = GLES20.glCreateProgram(); 
    if (program == 0) 
     throw new FmtException(FmtException.GLES, "could not create program: %s",getError()); 


    GLES20.glAttachShader(program, vertexShader); 
    GLES20.glAttachShader(program, pixelShader); 
    GLES20.glLinkProgram(program); 

    GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, gotVar, 0); 
    if (gotVar[0] != GLES20.GL_TRUE) { 
     GLES20.glGetProgramiv(program, GLES20.GL_INFO_LOG_LENGTH, gotVar, 0); 
     if (gotVar[0] != 0) { 
      GLES20.glDeleteProgram(program); 
      throw new FmtException(FmtException.GLES, "could not link program:\n%s\n", GLES20.glGetProgramInfoLog(program)); 
     } 
    } 

    return program; 
} 

jede Hilfe oder Vorschläge würden sehr geschätzt werden.

+3

Wo würdest du 'createProgram nennen()' in Ihrem Code? Ich weiß für eine Tatsache, dass 'createProgram()' 0 zurückgibt, wenn es außerhalb des GL-Threads aufgerufen wird. – Reigertje

+0

@Brianberg Es wird in der Game-Klasse onStart() -Methode aufgerufen, daher wird es in der onCreate() -Methode der MainActivity aufgerufen. – Jim

+9

Ja, das ist außerhalb des GL-Threads. Stellen Sie sicher, dass alle Methoden von GLES20 innerhalb des GL-Threads aufgerufen werden - andernfalls funktionieren sie nicht. Das ist in 'onSurfaceChanged()', 'onSurfaceCreated()' und/oder 'onDrawFrame()'. – Reigertje

Antwort

23

Für diejenigen, die nach der Antwort suchen, ist es in den Kommentaren versteckt. Ich rezitiere @Reigerta aus Kommentaren.

Shader Anrufe sollten innerhalb eines GL-Gewinde, die onSurfaceChanged ist(), onSurfaceCreated() oder onDrawFrame()