前言:
前面介紹了使用 Android 編寫(xiě) OpenGL ES 應(yīng)用的程序框架楞艾,并成功繪制了第一個(gè)OpenGL ES 2.0的小程序草讶,本篇介紹 3D 繪圖的一些基本構(gòu)成要素祭椰,基本概念泥张,重要的函數(shù),最終將實(shí)現(xiàn)一個(gè)頂點(diǎn)的繪制巧骚。
本文是建立在上一篇文章之上赊颠,只修改MyRenderer類格二,其他部分保持不變,如果你沒(méi)有看上一篇文章竣蹦,請(qǐng)先移步Android OpenGl ES2.0編程_第一個(gè)OpenGL小程序
▲ 基本概念
Vertex (頂點(diǎn))
頂點(diǎn)是3D建模時(shí)用到的最小構(gòu)成元素顶猜,頂點(diǎn)定義為兩條或是多條邊交會(huì)的地方。在 3D 模型中一個(gè)頂點(diǎn)可以為多條邊痘括,面或是多邊形所共享长窄。一個(gè)頂點(diǎn)也可以代表一個(gè)點(diǎn)光源或是 Camera 的位置。下圖中標(biāo)識(shí)為黃色的點(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)系的概念,這里我們不用理解的那么深椅贱,簡(jiǎn)單的知道和了解最基本的就好懂算,推薦閱讀三維坐標(biāo)系介紹
在3D繪圖中,坐標(biāo)軸遵循右手法則。三維坐標(biāo)系中庇麦,Z軸的正軸方向是根據(jù)右手定則確定的计技。右手定則也決定三維空間中任一坐標(biāo)軸的正旋轉(zhuǎn)方向。
要標(biāo)注X山橄、Y和Z軸的正軸方向垮媒,就將右手背對(duì)著屏幕放置,拇指即指向X軸的正方向航棱。伸出食指和中指睡雇,如右圖所示,食指指向Y軸的正方向,中指所指示的方向即是Z軸的正方向鳍悠。
要確定軸的正旋轉(zhuǎn)方向,如右圖所示,用右手的大拇指指向軸的正方向仿村,彎曲手指。那么手指所指示的方向即是軸的正旋轉(zhuǎn)方向鲤孵。
▲ 點(diǎn)的構(gòu)成
有了之前對(duì)坐標(biāo)系的理解瘩欺,我們知道,在3D繪制中沫屡,一個(gè)點(diǎn)包含x饵隙、y、z坐標(biāo)沮脖。在Android系統(tǒng)中,可以用一個(gè)float數(shù)組金矛、int數(shù)組等來(lái)表示一個(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();
//寫(xiě)入數(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場(chǎng)景的大小
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)功能及配置說(shuō)明
這里講解部分比較重要的函數(shù)娶耍,之后還有一些常用API在之后的文章會(huì)重點(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ù)組來(lái)讀取數(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ù)類型槽片,允許的符號(hào)常量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,則沒(méi)有設(shè)置緩沖區(qū)勃刨。
2. glClear()
用來(lái)清理緩沖區(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可以是下列符號(hào)常量:
GL_COLOR_ARRAY —— 如果啟用贾铝,顏色矩陣可以用來(lái)寫(xiě)入以及調(diào)用glDrawArrays方法或者glDrawElements方法時(shí)進(jìn)行渲染隙轻。詳見(jiàn)glColorPointer。
GL_NORMAL_ARRAY —— 如果啟用垢揩,法線矩陣可以用來(lái)寫(xiě)入以及調(diào)用glDrawArrays方法或者glDrawElements方法時(shí)進(jìn)行渲染玖绿。詳見(jiàn)glNormalPointer。
GL_TEXTURE_COORD_ARRAY —— 如果啟用叁巨,紋理坐標(biāo)矩陣可以用來(lái)寫(xiě)入以及調(diào)用glDrawArrays方法或者glDrawElements方法時(shí)進(jìn)行渲染斑匪。詳見(jiàn)glTexCoordPointer。
GL_VERTEX_ARRAY —— 如果啟用锋勺,頂點(diǎn)矩陣可以用來(lái)寫(xiě)入以及調(diào)用glDrawArrays方法或者glDrawElements方法時(shí)進(jìn)行渲染蚀瘸。詳見(jiàn)glVertexPointer狡蝶。
GL_POINT_SIZE_ARRAY_OES(OES_point_size_arrayextension)——如果啟用,點(diǎn)大小矩陣控制大小以渲染點(diǎn)和點(diǎn)sprites贮勃。這時(shí)由glPointSize定義的點(diǎn)大小將被忽略牢酵,由點(diǎn)大小矩陣 提供的大小將被用來(lái)渲染點(diǎn)和點(diǎn)sprites。詳見(jiàn)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ù)組緩存中的哪一位開(kāi)始繪制,一般都定義為0
count:頂點(diǎn)的數(shù)量
▲ 最終效果圖
看著雖然是一個(gè)正方形棵譬,但實(shí)際它是一個(gè)大小為100f的正方形的點(diǎn)