2012-10-03 1 views
6

Sto provando a creare un'applicazione che mostrerà il testo usando OpenGL. Ottengo un comportamento imprevisto quando provo a usare Matrix.translateM per spostare l'oggetto specificato in una posizione specifica. Tutte le altre matrici di trasformazione funzionano come mi aspetterei che facciano.Android OpenGL ES 2.0: non ottenere i risultati che voglio con Matrix.traslateM

Questo è ciò che ho quando chiamo Matrix.translateM(model_matrix, 0, -1.0f, 0, 0): result image

Questa è l'immagine senza traduzione: enter image description here

Questo è il mio codice di rendering.

@Override 
public void onSurfaceCreated(GL10 unused, EGLConfig config) { 
    GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); 
    GLES20.glDisable(GLES20.GL_DEPTH_TEST); 
    GLES20.glEnable(GLES20.GL_BLEND); 
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 

    // create programs 
    simple_texture = new SimpleTexture(); 

    // create shapes 
    square = new Square(); 

    // create debug text handlers 
    text_fps = new Text(this.font, this.text_scale); 
    text_fps.setSize(50); 
    text_fps.setText("Test\nLonger line"); 

    // set camera position 
    final float eyeX = 0.0f; 
    final float eyeY = 0.0f; 
    final float eyeZ = -3.0f; 

    final float lookX = 0.0f; 
    final float lookY = 0.0f; 
    final float lookZ = 0.0f; 

    final float upX = 0.0f; 
    final float upY = 1.0f; 
    final float upZ = 0.0f; 

    Matrix.setLookAtM(view_matrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); 
} 

@Override 
public void onSurfaceChanged(GL10 unused, int width, int height) { 
    GLES20.glViewport(0, 0, width, height); 

    // set projection matrix 
    float ratio = (float) width/height; 
    Matrix.orthoM(projection_matrix, 0, -ratio, ratio, -1, 1, 3, 7); 

    setScreenRatio(ratio); 
    setScreenHeight(height); 
} 

@Override 
public void onDrawFrame(GL10 unused) { 
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 

    // calculate projection and view transformation 
    Matrix.multiplyMM(vp_matrix, 0, projection_matrix, 0, view_matrix, 0); 

    // if we are connected to debugger draw statistics 
    drawStatistics(vp_matrix); 
} 

E questo è il mio codice draw per il testo.

// use predefined program 
    GLES20.glUseProgram(program); 

    // get attribute positions 
    attr_matrix = GLES20.glGetUniformLocation(program, "u_Matrix"); 
    attr_position = GLES20.glGetAttribLocation(program, "a_Position"); 
    attr_texture_position = GLES20.glGetAttribLocation(program, "a_TexturePosition"); 
    attr_texture = GLES20.glGetUniformLocation(program, "u_Texture"); 

    // set program parameters 
    GLES20.glEnableVertexAttribArray(attr_position); 
    GLES20.glVertexAttribPointer(attr_position, 2, GLES20.GL_FLOAT, false, 2 * 4, square_buffer); 

    // set texture parameters 
    GLES20.glEnableVertexAttribArray(attr_texture_position); 
    GLES20.glVertexAttribPointer(attr_texture_position, 2, GLES20.GL_FLOAT, false, 2 * 4, texture_buffer); 

    // set matrix 
    float[] result = new float[16]; 
    float ratio = (float) texture_height/texture_width; 
    float screen_scale = (float) texture_height/PageRenderer.getScreenHeight(); 

    Matrix.setIdentityM(model_matrix, 0); 
    Matrix.translateM(model_matrix, 0, -1, 0, 0); 
    Matrix.scaleM(model_matrix, 0, screen_scale, screen_scale * ratio, screen_scale); 

    Matrix.setIdentityM(result, 0); 
    Matrix.multiplyMM(result, 0, matrix, 0, model_matrix, 0); 
    GLES20.glUniformMatrix4fv(attr_matrix, 1, false, result, 0); 

    // assign texture 
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, index); 
    GLES20.glUniform1i(attr_texture, 0); 

    // perform drawing 
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 

    // disable vertex array 
    GLES20.glDisableVertexAttribArray(attr_position); 
    GLES20.glDisableVertexAttribArray(attr_texture_position); 

Shaders:

int vertex_shader = PageRenderer.loadShader(
      GLES20.GL_VERTEX_SHADER, 
      "uniform mat4 u_Matrix;" + 
      "attribute vec4 a_Position;" + 
      "attribute vec2 a_TexturePosition;" + 
      "varying vec2 v_TexturePosition;" + 
      "void main() {" + 
      " gl_Position = a_Position * u_Matrix;" + 
      " v_TexturePosition = a_TexturePosition;" + 
      "}" 
     ); 
    int fragment_shader = PageRenderer.loadShader(
      GLES20.GL_FRAGMENT_SHADER, 
      "precision mediump float;" + 
      "varying vec2 v_TexturePosition;" + 
      "uniform sampler2D u_Texture;" + 
      "void main() {" + 
      " gl_FragColor = texture2D(u_Texture, v_TexturePosition);" + 
      "}" 
     ); 

Scaling e il lavoro a rotazione come previsto, ma io non riesco a capire il motivo per cui tradurre non lo fa. Si prega di notare che non ho usato OpenGL fino a poco tempo fa.

Mi aspettavo per translateM spostare il testo a sinistra, non "ruotarlo".

+0

Che cosa è supposto per assomigliare? Cosa ti aspettavi? Inoltre, puoi mostrare i tuoi shader. – Tim

+0

@Tim cosa sicura. Ci scusiamo per la mancanza di dettagli. Ho aggiunto codice shader e immagine come appare senza 'translateM'. Mi aspettavo che 'translateM' sposasse l'immagine a sinistra. – MeanEYE

+0

Ah, mi dispiace. Trovato il problema ora che ho avuto una seconda occhiata al codice dello shader. :) Grazie. – MeanEYE

risposta

11

L'ordine delle variabili durante il calcolo di gl_Position è importante! La matrice del mondo va prima e poi le coordinate del vertice. Quando facevo una domanda, lo sapevo, ma non prestavo attenzione dal momento che il codice dello shader è preso dal tutorial Android OpenGL. Sii gente comune. Tutorial non è corretto!

codice dello shader corretta:

int vertex_shader = PageRenderer.loadShader(
      GLES20.GL_VERTEX_SHADER, 
      "uniform mat4 u_Matrix;" + 
      "attribute vec4 a_Position;" + 
      "attribute vec2 a_TexturePosition;" + 
      "varying vec2 v_TexturePosition;" + 
      "void main() {" + 
      " gl_Position = u_Matrix * a_Position;" + 
      " v_TexturePosition = a_TexturePosition;" + 
      "}" 
     ); 
    int fragment_shader = PageRenderer.loadShader(
      GLES20.GL_FRAGMENT_SHADER, 
      "precision mediump float;" + 
      "varying vec2 v_TexturePosition;" + 
      "uniform sampler2D u_Texture;" + 
      "void main() {" + 
      " gl_FragColor = texture2D(u_Texture, v_TexturePosition);" + 
      "}" 
     ); 
+0

La cosa più orribile è che questo bug è invisibile se disegni forme semplici e sarà disastroso quando disegni forme complesse. Grazie a MeanEYE !!! –

+0

Sto avendo lo stesso problema ma la tua soluzione arresta solo lo shader per me. Posso solo ottenere le cose da renderizzare quando faccio 'gl_position = a_Position * u_Matrix'. Ho anche provato a cambiare l'ordine di moltiplicazione di vista e proiezione (per calcolare 'u_Matrix') senza alcun risultato. Qualche idea? Il tuo lavoro ha funzionato immediatamente quando hai scambiato V e M o hai dovuto fare qualcos'altro prima? – Navigateur

+0

Sì, ha funzionato subito se non ricordo male. Forse c'è qualcos'altro che non va nel tuo shader ma solo nei casi in cui fai le cose per bene. La mia esperienza con OpenGL è davvero limitata. Suggerisco di pubblicare una nuova domanda su SO. – MeanEYE