2017-03-04 49 views
0

我正在用OpenGL ES 2.0構建Java(Android)中的精靈(具有紋理的矩形)類。OpenGL ES 2.0矢量翻譯不能通過矩陣乘法工作(在頂點着色器中)

我的目標是隻使用紋理的一部分,因此我將一個矩陣傳遞給頂點着色器。在下面的例子中,我想只看到紋理的右半部分(但我seing左一半),規模在整個精靈寬度:

/ 0.5, 0, 0, 0.5 \ /x \  /0.5 * x + 0.5 \ 
| 0 , 1, 0, 0 | \/ | y | --- |  y  | 
| 0 , 0, 1, 0 | /\ | 1 | --- |  1  | 
\ 0 , 0, 0, 1 / \ 1/  \  1  /

如果我把我的紋理座標,它工作得很好(在紙上):

(0,1) -> (0.5,1) // bottom left 
(1,1) -> (1, 1) // bottom right 
(0,0) -> (0.5,0) // top left 
(1,0) -> (1, 0) // top right 

但在現實中,我得到這些結果:

(0,1) -> (0 ,1) 
(1,1) -> (0.5,1) 
(0,0) -> (0 ,0) 
(1,0) -> (0.5,0) 

這意味着縮放部作品,但翻譯部分沒有。

代碼

的Vertex Shader

attribute vec4 position; 
attribute vec2 texturePosition; 
uniform mat4 mvpMatrix; 
uniform mat4 textureMatrix; 
varying vec2 iTexturePosition; 
void main() { 
    gl_Position = mvpMatrix * position; 

    vec4 tp = vec4(texturePosition.x, texturePosition.y, 1, 1); 
    tp = textureMatrix * tp; 
    //tp[0] += 0.5; 
    iTexturePosition = tp.xy; 
} 

片段着色器

precision mediump float; 
uniform sampler2D textureUnit; 
varying vec2 iTexturePosition; 
void main() { 
    vec4 color = texture2D(textureUnit, iTexturePosition); 
    if (color.a <= 0.25) { 
    discard; 
    } 
    if (iTexturePosition[0] <= 0.4) { 
    //discard; 
    } 
    gl_FragColor = color; 
} 

Java端

private static int textureMatrixHandle = -1; 
private static final String textureMatrixName = "textureMatrix"; 
private float[] textureMatrix = new float[16]; 

// more code ... 

@Override 
public void draw { // only relevant lines 
    textureMatrixHandle = GLES20.glGetUniformLocation(glProgram, textureMatrixName); 

    Matrix.setIdentityM(textureMatrix, 0); 
    setTextureSection(textureMatrix, 0, 0.5f, 1, 1, 0); 

    GLES20.glUniformMatrix4fv(textureMatrixHandle, 1, false, textureMatrix, 0); 

    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, VERTEX_COUNT); 
} 

protected void translateTextureSection(float[] textureMatrix, float x, float y) { 
    Matrix.multiplyMM(textureMatrix, 0, new float[] { 
      1, 0, 0, x, 
      0, 1, 0, y, 
      0, 0, 1, 0, 
      0, 0, 0, 1, 
    }, 0, textureMatrix, 0); 
} 

protected void scaleTextureSection(float[] textureMatrix, float x, float y) { 
    Matrix.multiplyMM(textureMatrix, 0, new float[] { 
      x, 0, 0, 0, 
      0, y, 0, 0, 
      0, 0, 1, 0, 
      0, 0, 0, 1, 
    }, 0, textureMatrix, 0); 
} 

protected void rotateTextureSection(float[] textureMatrix, float angle) { 
    angle = (float) Math.toRadians(angle); 
    float sin = (float) Math.sin(angle); 
    float cos = (float) Math.cos(angle); 
    Matrix.multiplyMM(textureMatrix, 0, new float[] { 
      cos, -sin, 0, 0, 
      sin, cos, 0, 0, 
       0, 0, 1, 0, 
       0, 0, 0, 1, 
    }, 0, textureMatrix, 0); 
} 

protected void setTextureSection(float[] textureMatrix, float rotationAngle, float left, float right, float bottom, float top) { 
    rotateTextureSection(textureMatrix, rotationAngle); 
    translateTextureSection(textureMatrix, left, top); 
    scaleTextureSection(textureMatrix, right - left, bottom - top); 
} 
+0

當你調用glUniformMatrixf4v(或不管它是什麼)時,你是否傳遞真或假的轉置標誌? – samgak

+0

我錯過了。如我所料,縮放發生在x座標上(我正在拼接紋理的全高和寬度的一半,它只是寬度的錯誤的一半) – EvilDevil

+0

@samgak我正在像這樣設置制服:GLES20.glUniformMatrix4fv( textureMatrixHandle,1,false,textureMatrix,0); – EvilDevil

回答

0

問題是Java正在使用行主矩陣,而OGL ES only supports column-major matrices。含義如下矩陣

(0.5, 0.0, 0.0, 0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) 

被解讀爲

/ 0.5, 0, 0, 0 \ /x \  /0.5 * x   \ 
| 0 , 1, 0, 0 | \/ | y | --- |  y   | 
| 0 , 0, 1, 0 | /\ | 1 | --- |  1   | 
\ 0.5, 0, 0, 1/ \ 1/  \  1 + 0.5 * x/

這顯然不轉的座標。

在將它傳遞給OGL ES之前轉換矩陣解決了這個問題。

0

問題出在你打電話的方式Matrix.MultiplyMM。如果將結果數組的相同元素用作其中一個輸入,則結果是不確定的:

可以爲result,lhs和/或rhs傳遞相同的浮點數組。但是,如果結果元素與lhs或rhs元素重疊,則結果元素值未定義。

因此,改變你的函數使用的臨時矩陣,如:

float[] tempMatrix = new float[16]; 
protected void translateTextureSection(float[] textureMatrix, float x, float y) {   
    Matrix.multiplyMM(tempMatrix, 0, new float[] { 
      1, 0, 0, 0, 
      0, 1, 0, 0, 
      0, 0, 1, 0, 
      x, y, 0, 1, 
    }, 0, textureMatrix, 0); 
    System.arraycopy(tempMatrix, 0, textureMatrix, 0, tempMatrix.length); 
} 

此外,矩陣需要被移位,因爲Open GL的使用列優先的順序,但你逝去的float數組是行主要訂單。在調用glUniformMatrixf4v時設置轉置標誌在Open GLES中不受支持,因此您需要自己完成。

+0

但矩陣看起來預期: textureMatrix = {漂浮[16] @ 831879063544} (0.5,0.0,0.0,0.5,0.0,1.0,0.0,0.0,0.0,0.0, 1.0,0.0,0.0,0.0,0.0,1.0) – EvilDevil

+1

嘗試轉置矩陣,並將其轉置標誌設置爲false傳入。該標誌顯然不受支持http://gamedev.stackexchange.com/questions/15032/why-must-the-transpose-value-of-gluniformmatrix4fv-in-webgl-opengl-es-be-false – samgak