2017-03-04 16 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) 

スケーリング一部が動作することを意味するが、翻訳部分はありません。

コード

バーテックスシェーダ

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(またはそれが何であれ)を呼び出すときに、transposeフラグにtrueまたはfalseを渡していますか? – samgak

+0

私はfalseを渡しています。 (私はテクスチャの全体の高さと幅の半分を見ています、それは幅のちょうど間違った半分です) – 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と呼んでいることです。結果配列の同じ要素が入力の1つとして使用されている場合、結果は未定義です。

result、lhs、および/またはrhsに同じfloat配列が渡される可能性があります。ただし、結果要素が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); 
} 

また、オープン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

自分自身で行列を転置し、transposeフラグをfalseに設定して渡してみてください。フラグは明らかにサポートされていませんhttp://gamedev.stackexchange.com/questions/15032/why-must-the-transpose-value-of-gluniformmatrix4fv-in-webgl-opengl-es-be-false – samgak

関連する問題