Android OpenGl ES2.0編程_相關(guān)概念與繪制頂點(diǎn)

前言
前面介紹了使用 Android 編寫 OpenGL ES 應(yīng)用的程序框架,并成功繪制了第一個(gè)OpenGL ES 2.0的小程序,本篇介紹 3D 繪圖的一些基本構(gòu)成要素,基本概念,重要的函數(shù),最終將實(shí)現(xiàn)一個(gè)頂點(diǎn)的繪制。
本文是建立在上一篇文章之上,只修改MyRenderer類,其他部分保持不變,如果你沒有看上一篇文章,請先移步Android OpenGl ES2.0編程_第一個(gè)OpenGL小程序

▲ 基本概念

Vertex (頂點(diǎn))
頂點(diǎn)是3D建模時(shí)用到的最小構(gòu)成元素,頂點(diǎn)定義為兩條或是多條邊交會的地方。在 3D 模型中一個(gè)頂點(diǎn)可以為多條邊,面或是多邊形所共享。一個(gè)頂點(diǎn)也可以代表一個(gè)點(diǎn)光源或是 Camera 的位置。下圖中標(biāo)識為黃色的點(diǎn)為一個(gè)頂點(diǎn)(Vertex)。

三維坐標(biāo)系

三維笛卡兒坐標(biāo)系是在二維笛卡兒坐標(biāo)系的基礎(chǔ)上根據(jù)右手定則增加第三維坐標(biāo)(即Z軸)而形成的。同二維坐標(biāo)系一樣,AutoCAD中的三維坐標(biāo)系有世界坐標(biāo)系WCS(World Coordinate System)和用戶坐標(biāo)系UCS(User Coordinate System)兩種形式。---百度百科

學(xué)習(xí)OpenGL編程,少不了需要了解坐標(biāo)系的概念,這里我們不用理解的那么深,簡單的知道和了解最基本的就好,推薦閱讀三維坐標(biāo)系介紹

在3D繪圖中,坐標(biāo)軸遵循右手法則。三維坐標(biāo)系中,Z軸的正軸方向是根據(jù)右手定則確定的。右手定則也決定三維空間中任一坐標(biāo)軸的正旋轉(zhuǎn)方向。
要標(biāo)注X、Y和Z軸的正軸方向,就將右手背對著屏幕放置,拇指即指向X軸的正方向。伸出食指和中指,如右圖所示,食指指向Y軸的正方向,中指所指示的方向即是Z軸的正方向。
要確定軸的正旋轉(zhuǎn)方向,如右圖所示,用右手的大拇指指向軸的正方向,彎曲手指。那么手指所指示的方向即是軸的正旋轉(zhuǎn)方向。

▲ 點(diǎn)的構(gòu)成
有了之前對坐標(biāo)系的理解,我們知道,在3D繪制中,一個(gè)點(diǎn)包含x、y、z坐標(biāo)。在Android系統(tǒng)中,可以用一個(gè)float數(shù)組、int數(shù)組等來表示一個(gè)點(diǎn)。如下:

private float[] mArrayVertex = { 0f, 0f, 0f };

為了提高性能,通常將這些數(shù)組存放到 java.io 中定義的 Buffer 類中
新建一個(gè)工具類ToolUtils,把獲取Buffer數(shù)據(jù)的代碼封裝如下

public class ToolUtils {
    /**
     * @param vertexes float 數(shù)組
     * @return 獲取浮點(diǎn)形緩沖數(shù)據(jù)
     */
    public static FloatBuffer getFloatBuffer(float[] vertexes) {
        FloatBuffer buffer;
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertexes.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        buffer = vbb.asFloatBuffer();
        //寫入數(shù)組
        buffer.put(vertexes);
        //設(shè)置默認(rèn)的讀取位置
        buffer.position(0);
        return buffer;
    }
}

▲ 繪制一個(gè)點(diǎn)
這里只需修改MyRenderer類的代碼,其余代碼和之前搭建的基礎(chǔ)框架一樣。MyRenderer.java

public class MyRenderer implements GLSurfaceView.Renderer {
    //頂點(diǎn)數(shù)組
    private float[] mArrayVertex = { 0f, 0f, 0f };

    // 緩沖區(qū)
    private FloatBuffer mBuffer;

    MyRenderer() {
        //獲取浮點(diǎn)形緩沖數(shù)據(jù)
        mBuffer = ToolUtils.getFloatBuffer(mArrayVertex);
    }

    // Surface創(chuàng)建的時(shí)候調(diào)用
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // 設(shè)置清屏顏色為黑色(rgba)
        gl.glClearColor(0f, 0f, 0f, 0f);
    }

    // Surface改變的的時(shí)候調(diào)用
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // 設(shè)置OpenGL場景的大小
        gl.glViewport(width / 4, width / 2, width / 2, height / 2);
    }

    // 在Surface上繪制的時(shí)候調(diào)用
    @Override
    public void onDrawFrame(GL10 gl) {

        // 清除屏幕
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        // 允許設(shè)置頂點(diǎn) // GL10.GL_VERTEX_ARRAY頂點(diǎn)數(shù)組
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        // 設(shè)置頂點(diǎn)
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mBuffer);

        //設(shè)置點(diǎn)的顏色為紅色
        gl.glColor4f(1f, 0f, 0f, 0f);

        //設(shè)置點(diǎn)的大小
        gl.glPointSize(100f);

        // 繪制點(diǎn)
        gl.glDrawArrays(GL10.GL_POINTS, 0, 1);

        // 禁止頂點(diǎn)設(shè)置
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }
}

▲ 啟用相關(guān)功能及配置說明
這里講解部分比較重要的函數(shù),之后還有一些常用API在之后的文章會重點(diǎn)講到

0. glClearColor()
設(shè)置清屏顏色,每次清屏?xí)r,使用該顏色填充整個(gè)屏幕。里面參數(shù)分別代表RGBA,取值范圍為[0,1]而不是[0,255]。例如:

gl.glClearColor(0f, 0f, 0f, 0f);

1. glVertexPointer()
設(shè)置一個(gè)指針,這個(gè)指針指向頂點(diǎn)數(shù)組,后面繪制三角形(或矩形)根據(jù)這里指定的頂點(diǎn)數(shù)組來讀取數(shù)據(jù)
函數(shù)原型:

void glVertexPointer(int size,int type,int stride,Buffer pointer)

參數(shù)解釋

size —— 每個(gè)頂點(diǎn)的坐標(biāo)維數(shù),必須是2, 3 或者4,初始值是4。

type —— 指明每個(gè)頂點(diǎn)坐標(biāo)的數(shù)據(jù)類型,允許的符號常量GL_BYTE, GL_SHORT,GL_FIXED 和GL_FLOAT,初始值為GL_FLOAT。

stride —— 指明連續(xù)頂點(diǎn)間的位偏移,如果為0,頂點(diǎn)被認(rèn)為是緊密壓入矩陣,初始值為0。

pointer —— 指明頂點(diǎn)坐標(biāo)的緩沖區(qū),如果為null,則沒有設(shè)置緩沖區(qū)。

2. glClear()
用來清理緩沖區(qū),并設(shè)置為預(yù)設(shè)值
函數(shù)原型:

glClear(int mask)

mask的值有以下三種

GL_COLOR_BUFFER_BIT —— 表明顏色緩沖區(qū)

GL_DEPTH_BUFFER_BIT —— 表明深度緩沖

GL_STENCIL_BUFFER_BIT —— 表明模型緩沖區(qū)

3. glEnableClientState()
啟用客戶端的某項(xiàng)功能。glEnableClientState和glDisableClientState啟用或禁用客戶端的單個(gè)功能。默認(rèn)的,所有客戶端功能禁用。 array可以是下列符號常量:

GL_COLOR_ARRAY —— 如果啟用,顏色矩陣可以用來寫入以及調(diào)用glDrawArrays方法或者glDrawElements方法時(shí)進(jìn)行渲染。詳見glColorPointer。

GL_NORMAL_ARRAY —— 如果啟用,法線矩陣可以用來寫入以及調(diào)用glDrawArrays方法或者glDrawElements方法時(shí)進(jìn)行渲染。詳見glNormalPointer。

GL_TEXTURE_COORD_ARRAY —— 如果啟用,紋理坐標(biāo)矩陣可以用來寫入以及調(diào)用glDrawArrays方法或者glDrawElements方法時(shí)進(jìn)行渲染。詳見glTexCoordPointer。

GL_VERTEX_ARRAY —— 如果啟用,頂點(diǎn)矩陣可以用來寫入以及調(diào)用glDrawArrays方法或者glDrawElements方法時(shí)進(jìn)行渲染。詳見glVertexPointer。

GL_POINT_SIZE_ARRAY_OES(OES_point_size_arrayextension)——如果啟用,點(diǎn)大小矩陣控制大小以渲染點(diǎn)和點(diǎn)sprites。這時(shí)由glPointSize定義的點(diǎn)大小將被忽略,由點(diǎn)大小矩陣 提供的大小將被用來渲染點(diǎn)和點(diǎn)sprites。詳見glPointSize。

4. glDrawArrays()
繪制數(shù)組里面所有點(diǎn)構(gòu)成的各個(gè)三角片
函數(shù)原型:

void glDrawArrays(
    int mode,
    int first,
    int count
);

參數(shù)解釋

mode:有三種取值

  • GL_TRIANGLES:每三個(gè)頂之間繪制三角形,之間不連接
  • GL_TRIANGLE_FAN:以V0 V1 V2,V0 V2 V3,V0 V3 V4,……的形式繪制三角形
  • GL_TRIANGLE_STRIP:順序在每三個(gè)頂點(diǎn)之間均繪制三角形。這個(gè)方法可以保證從相同的方向上所有三角形均被繪制。以V0 V1 V2 ,V1 V2 V3,V2 V3 V4,……的形式繪制三角形

first:從數(shù)組緩存中的哪一位開始繪制,一般都定義為0

count:頂點(diǎn)的數(shù)量

▲ 最終效果圖
看著雖然是一個(gè)正方形,但實(shí)際它是一個(gè)大小為100f的正方形的點(diǎn)

▲ 完整代碼下載:https://github.com/ChenYXin/OpenGL_ES_2.0_Sample

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容