對Android opengl ES全局座標系和紋理座標系的理解

來源:互聯網
上載者:User

對Android opengl ES全局座標系和紋理座標系的理解

初學opengl ES,每一個教你在螢幕上貼圖的opengl版hello world都有這麼兩數組:

    static final float COORD[] = {            -1.0f, -1.0f,            1.0f, -1.0f,            -1.0f, 1.0f,            1.0f, 1.0f,    };    static final float TEXTURE_COORD[] = {            0.0f, 1.0f,            1.0f, 1.0f,            0.0f, 0.0f,            1.0f, 0.0f,    };

但是幾乎都不解釋,所以我學的時候都不明白這些點為什麼要這麼寫,前後順序有沒有什麼規律。於是各種查資料實驗,終於搞懂了。

1.座標系

PS:本人學opengl es主要是為了2D貼圖,所以不涉及Z軸

,圖一是opengl的全局座標系,這個基本沒啥問題,主要是很多教程說紋理座標是左下原點。實踐得出在Android上應該是最右邊的圖那樣,以左上為原點。
個人猜測紋理吧其實就是一組顏色點組成的數組,Android由於UI座標是以左上為原點,所以把數組裡顏色點的儲存順序改了一下,於是座標系就不一樣了。

2.範例程式碼
public class Filter {    protected static final String VERTEX_SHADER = "" +            "attribute vec4 position;\n" +            "attribute vec4 inputTextureCoordinate;\n" +            " \n" +            "varying vec2 textureCoordinate;\n" +            " \n" +            "void main()\n" +            "{\n" +            "    gl_Position = position;\n" +            "    textureCoordinate = inputTextureCoordinate.xy;\n" +            "}";    protected static final String FRAGMENT_SHADER = "" +            "varying highp vec2 textureCoordinate;\n" +            " \n" +            "uniform sampler2D inputImageTexture;\n" +            " \n" +            "void main()\n" +            "{\n" +            "     gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n" +            "}";    static final float COORD1[] = {            -1.0f, -1.0f,            1.0f, -1.0f,            -1.0f, 1.0f,            1.0f, 1.0f,    };    static final float TEXTURE_COORD1[] = {            0.0f, 1.0f,            1.0f, 1.0f,            0.0f, 0.0f,            1.0f, 0.0f,    };    static final float COORD2[] = {            -1.0f, 1.0f,            -1.0f, -1.0f,            1.0f, 1.0f,            1.0f, -1.0f,    };    static final float TEXTURE_COORD2[] = {            0.0f, 0.0f,            0.0f, 1.0f,            1.0f, 0.0f,            1.0f, 1.0f,    };    static final float COORD3[] = {            1.0f, -1.0f,            1.0f, 1.0f,            -1.0f, -1.0f,            -1.0f, 1.0f,    };    static final float TEXTURE_COORD3[] = {            1.0f, 1.0f,            1.0f, 0.0f,            0.0f, 1.0f,            0.0f, 0.0f,    };    static final float COORD4[] = {            1.0f, -1.0f,            1.0f, 1.0f,            -1.0f, -1.0f,            -1.0f, 1.0f,    };    static final float TEXTURE_COORD4[] = {            1.0f, 1.0f,            1.0f, 0.0f,            0.0f, 1.0f,            0.0f, 0.0f,    };    static final float COORD_REVERSE[] = {            1.0f, -1.0f,            1.0f, 1.0f,            -1.0f, -1.0f,            -1.0f, 1.0f,    };    static final float TEXTURE_COORD_REVERSE[] = {            1.0f, 0.0f,            1.0f, 1.0f,            0.0f, 0.0f,            0.0f, 1.0f,    };    static final float COORD_FLIP[] = {            1.0f, -1.0f,            1.0f, 1.0f,            -1.0f, -1.0f,            -1.0f, 1.0f,    };    static final float TEXTURE_COORD_FLIP[] = {            0.0f, 1.0f,            0.0f, 0.0f,            1.0f, 1.0f,            1.0f, 0.0f,    };    private String mVertexShader;    private String mFragmentShader;    private FloatBuffer mCubeBuffer;    private FloatBuffer mTextureCubeBuffer;    protected int mProgId;    protected int mAttribPosition;    protected int mAttribTexCoord;    protected int mUniformTexture;    public Filter() {        this(VERTEX_SHADER, FRAGMENT_SHADER);    }    public Filter(String vertexShader, String fragmentShader) {        mVertexShader = vertexShader;        mFragmentShader = fragmentShader;    }    public void init() {        loadVertex();        initShader();        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);    }    public void loadVertex() {        float[] coord = COORD1;        float[] texture_coord = TEXTURE_COORD1;        mCubeBuffer = ByteBuffer.allocateDirect(coord.length * 4)                .order(ByteOrder.nativeOrder())                .asFloatBuffer();        mCubeBuffer.put(coord).position(0);        mTextureCubeBuffer = ByteBuffer.allocateDirect(texture_coord.length * 4)                .order(ByteOrder.nativeOrder())                .asFloatBuffer();        mTextureCubeBuffer.put(texture_coord).position(0);    }    public void initShader() {        mProgId = GLHelper.loadProgram(mVertexShader, mFragmentShader);        mAttribPosition = GLES20.glGetAttribLocation(mProgId, "position");        mUniformTexture = GLES20.glGetUniformLocation(mProgId, "inputImageTexture");        mAttribTexCoord = GLES20.glGetAttribLocation(mProgId,                "inputTextureCoordinate");    }    public void drawFrame(int glTextureId) {        if (!GLES20.glIsProgram(mProgId)) {            initShader();        }        GLES20.glUseProgram(mProgId);        mCubeBuffer.position(0);        GLES20.glVertexAttribPointer(mAttribPosition, 2, GLES20.GL_FLOAT, false, 0, mCubeBuffer);        GLES20.glEnableVertexAttribArray(mAttribPosition);        mTextureCubeBuffer.position(0);        GLES20.glVertexAttribPointer(mAttribTexCoord, 2, GLES20.GL_FLOAT, false, 0,                mTextureCubeBuffer);        GLES20.glEnableVertexAttribArray(mAttribTexCoord);        if (glTextureId != GLHelper.NO_TEXTURE) {            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, glTextureId);            GLES20.glUniform1i(mUniformTexture, 0);        }        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);        GLES20.glDisableVertexAttribArray(mAttribPosition);        GLES20.glDisableVertexAttribArray(mAttribTexCoord);        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);        GLES20.glDisable(GLES20.GL_BLEND);    }}

其中
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
由於openglES本身就是opengl的縮減版,所以能直接畫的形狀就只有三角形,別的複雜的都要由三角形來組成。GLES20.GL_TRIANGLE_STRIP指的就是一種三角形的繪製模式,對應這個頂點數組:

  static final float COORD[] = {            -1.0f, -1.0f,  //1            1.0f, -1.0f,   //2            -1.0f, 1.0f,   //3            1.0f, 1.0f,    //4    };

實際繪製的就是頂點1,2,3組成的三角形和頂點2,3,4組成的三角形合并成的一個矩形,如果有更多點,依次類推(比如有5個點,就是1,2,3 2,3,4 3,4,5三個三角形組成的圖案)。如:

3.紋理頂點順序

紋理的點和全局座標的點之間是對應的:

    static final float COORD1[] = {            -1.0f, -1.0f,            1.0f, -1.0f,            -1.0f, 1.0f,            1.0f, 1.0f,    };    static final float TEXTURE_COORD1[] = {            0.0f, 1.0f,            1.0f, 1.0f,            0.0f, 0.0f,            1.0f, 0.0f,    };

顯示結果

中箭頭,opengl會把紋理中顏色頂點繪到對應的全局座標頂點上,中間的點則按一定的規律取個平均值什麼的,所以可見實際顯示的圖被上下展開了,因為原圖是1:1,而在該程式裡
GLES20.glViewport(0, 0, width, height);
賦予的顯示地區是高大於寬的(這裡涉及到opengl全局座標和螢幕座標的映射,和本文主旨關係不大就不多說了)。

其實也就是只要全局座標和紋理座標數組裡的點能夠對的上,順序不是問題
代碼裡的四組座標的顯示效果都是一樣的:

 static final float COORD1[] = {            -1.0f, -1.0f,            1.0f, -1.0f,            -1.0f, 1.0f,            1.0f, 1.0f,    };    static final float TEXTURE_COORD1[] = {            0.0f, 1.0f,            1.0f, 1.0f,            0.0f, 0.0f,            1.0f, 0.0f,    };    static final float COORD2[] = {            -1.0f, 1.0f,            -1.0f, -1.0f,            1.0f, 1.0f,            1.0f, -1.0f,    };    static final float TEXTURE_COORD2[] = {            0.0f, 0.0f,            0.0f, 1.0f,            1.0f, 0.0f,            1.0f, 1.0f,    };    static final float COORD3[] = {            1.0f, -1.0f,            1.0f, 1.0f,            -1.0f, -1.0f,            -1.0f, 1.0f,    };    static final float TEXTURE_COORD3[] = {            1.0f, 1.0f,            1.0f, 0.0f,            0.0f, 1.0f,            0.0f, 0.0f,    };    static final float COORD4[] = {            1.0f, -1.0f,            1.0f, 1.0f,            -1.0f, -1.0f,            -1.0f, 1.0f,    };    static final float TEXTURE_COORD4[] = {            1.0f, 1.0f,            1.0f, 0.0f,            0.0f, 1.0f,            0.0f, 0.0f,    };

不信的可以在這裡都替換了試試:

      float[] coord = COORD1;      float[] texture_coord = TEXTURE_COORD1;

為了加深理解,甚至可以玩點花樣出來,比如這樣

    static final float COORD_REVERSE[] = {            1.0f, -1.0f,            1.0f, 1.0f,            -1.0f, -1.0f,            -1.0f, 1.0f,    };    static final float TEXTURE_COORD_REVERSE[] = {            1.0f, 0.0f,            1.0f, 1.0f,            0.0f, 0.0f,            0.0f, 1.0f,    };  。。。。。。。。。。。。。。。。      float[] coord = COORD_REVERSE;      float[] texture_coord = TEXTURE_COORD_REVERSE;

結果如:

4.Demo源碼地址

https://github.com/yellowcath/GLCoordDemo.git

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.