OpenGL均採用三角形列表進行渲染.每個三角形都有三個頂點.在有些情況下兩個或多個三角形會共用頂點.如上圖有兩個頂點具有相同『位置』『顏色』『紋理座標』.但甘浪費空間.更好解卻方法是將所有頂點保存在列表.而三角形頂點保存索引.OpenGL ES要求索引值使用短整數或字節.即OpenGL ES每次最多渲染65536個頂點.
我地需要一個Vertices類,用於存儲每個頂點『位置』『顏色』與『紋理座標』,並且它需要兩個選項.頂點是否『顏色』與『紋理座標』
public class VERTICES {
boolean color_have = false;// 擁有顏色
boolean texture_have =false;// 擁有紋理坐標
int vertex_size = 0;// 每個頂點所占大小
使用FloatBuffer保存頂點
FloatBuffer vertex_array = null;
使用ShortBuffer頂點索引
ShortBuffer index_array = null;
頂點隊列分配記憶體,vertex_max為最大頂點量, index_max為最大索引量
VERTICES(int vertex_max,int index_max,boolean color_have,boolean texture_have){
this.color_have = color_have;// 擁有頂點顏色
this.texture_have = texture_have;// 擁有紋理坐標
計算每頂點所占大小.顏色占4單元.紋理座標占2單元.2D座標占2單元.每個整數占4字節
int vertex_size = (2 + (color_have?4:0) + (texture_have?2:0) ) * 4;
因為OpenGL ES是以C API結口提供.無法直接使用JAVA數組.因此你需要C數組系統堆棧記憶體.而非JAVA虛擬機記憶體.需要 FloatBuffer分配頂點記憶體.
vertex_max為最大頂點量.
ByteBuffer buffer = ByteBuffer.allocateDirect(vertex_size * vertex_max);
將『網絡字節』改為『主機字節』或稱為『CPU字節』
buffer.order(ByteOrder.nativeOrder());
獲取整數數組
vertex_array = buffer.asIntBuffer();
每個短整形占兩個字節.index_max為最大索引量
buffer = ByteBuffer.allocateDirect(index_max * Short.SIZE/8);
將『網絡字節』改為『主機字節』
buffer.order(ByteOrder.nativeOrder());
頂點短整數數組
index_array = buffer.asShortBuffer();
}
將頂點提交給OpenGL數組並觸發
public void SetVertices(float[] vertices,int offset,int count){
vertex_array.clear();// 清空緩存.設定當前位置
int len = offset + count;
for(int i=offset, j=0; i < len; i++, j++)
vertex_Buffer[j] = Float.floatToRawIntBits(vertices[i]);
vertex_array.put(vertex_Buffer, 0, count); // 寫入數據.移動當前位置
vertex_array.flip();// 觸發
}
將頂點索引提交給OpenGL數組
public void SetIndices(short[] indices,int offset,int count) {
index_array.clear();// 清空緩存.設定當前位置
index_array.put(indices, offset, count); // 寫入數據.移動當前位置
index_array.flip();// 觸發
}
綁定數據
public void Bind(){
GL10 gl = GRAPHICS.gl;
啟用頂點數組
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
設置當前寫入位置0
vertex_array.position(0);
設置頂點指針,每個頂點兩個元素.xy兩分量
gl.glVertexPointer(2, GL10.GL_FLOAT, vertex_size, vertex_array);
if(color_have == true){//顏色
啟用頂點顏色數組
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
設置當前寫入位置2
vertex_array.position(2);
設置顏色指針,RGBA四分量
gl.glColorPointer(4, GL10.GL_FLOAT, vertex_size, vertex_array);
}
if(texture_have ){// 紋理坐標
啟用紋理坐標數組
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
vertex_array.position(color_have?6:2);// 寫入位置
設置紋理坐標指針,UV兩分量
gl.glTexCoordPointer(2, GL10.GL_FLOAT, vertex_size, vertex_array);
}
}
取消綁定數據
public void Unbind(){
GL10 gl = GRAPHICS.gl;
關閉頂點紋理數組
if(color_have)
gl.glDisableClientState(GL10.GL_COLOR_ARRAY );
關閉頂點顏色數組
if(texture_have)
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
繪畫三角形
public void Draw(int mode,int offset,int count){
GL10 gl = GRAPHICS.gl;
繪畫頂點
if(index_array != null){// 繪畫
index_array.position(offset);//
gl.glDrawElements(mode, count, GL10.GL_UNSIGNED_SHORT, index_array);
}
else{
gl.glDrawArrays(mode, offset, count);
}
}
}