2017-03-04 52 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