OpenGL在java層實(shí)現(xiàn)制圖博杖,一般都是通過GlsurfaceView來顯示的 屡谐,
以下內(nèi)容源于:<a >傳送門</a>
(加小部分的個(gè)人理解)
先介紹下GlSurfaceView的幾個(gè)特點(diǎn):
1、管理一個(gè)平面籍琳,這個(gè)平面是一個(gè)特殊的內(nèi)存塊菲宴,它可以和android視圖系統(tǒng)混合
2、管理一個(gè)EGL顯示趋急,他能夠讓OpenGl渲染到一個(gè)屏幕喝峦,關(guān)于EGL 是個(gè)什么鬼,詳見:<a >EGL接口解析與理解</a>
3呜达、接受一個(gè)用戶提供的實(shí)際顯示的Renderer對(duì)象(...渲染器谣蠢,可以理解為GlSurface是畫布,而Renderer是畫筆查近,文中通過setRenderer(mRenderer)關(guān)聯(lián)起來)
4眉踱、使用一個(gè)專用線程去渲染從而和UI線程解耦(話說SurfaceView 也是可以直接在子線程更新UI的說)
5、支持on-demand和連續(xù)的渲染
6霜威、可選的包谈喳,追蹤或者錯(cuò)誤檢查這個(gè)渲染器的OpenGl調(diào)用
接下來直接上代碼:
public class MainActivity extends AppCompatActivity {
private GLSurfaceView glSurfaceVie;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceVie= new GLSurfaceView(this);
setContentView(glSurfaceVie);
glSurfaceVie.setRenderer(new EffectsRender(this));
}
@Override
protected void onResume() {
super.onResume();
glSurfaceVie.onResume();
}
@Override
protected void onPause() {
super.onPause();
glSurfaceVie.onPause();
}
}
//渲染器
public class EffectsRender implements GLSurfaceView.Renderer {
private Bitmap mBitmap;
private int photow,photoh;
private int textures[] = new int[2];
private Square square;
private Context mContext;
public EffectsRender(Context context) {
super();
this.mContext =context;
square = new Square();
/* mBitmap = BitmapFactory.decodeResource(context.getResources(),R.mipmap.bitmap);
photow=mBitmap.getWidth();
photoh =mBitmap.getHeight();*/
}
private void getSquare(){
GLES20.glGenTextures(2,textures,0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textures[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//清除屏幕顏色
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
//
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
//這里告訴OpenGL我們希望進(jìn)行最好的透視修正。這會(huì)十分輕微的影響性能戈泼。但使得透視圖看起來好一點(diǎn).
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_NICEST);
//啟用smooth shading(陰影平滑).陰影平滑通過多邊形精細(xì)的混合色彩婿禽,并對(duì)外部光進(jìn)行平滑
gl.glShadeModel(GL10.GL_SMOOTH);
// 關(guān)閉服務(wù)器端GL功能,在GL中很多都是一對(duì)一對(duì)的,比如這個(gè)的另一個(gè)gl.glEnable(...).
gl.glDisable(GL10.GL_DITHER);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height==0){
height=1;
}
float aspect=(float)width/height;
//設(shè)置可見區(qū)域
gl.glViewport(0,0,width,height);
//有3種模式: GL_PROJECTION 投影, GL_MODELVIEW 模型視圖, GL_TEXTURE 紋理.===>處理之前提前告訴計(jì)算機(jī),
gl.glMatrixMode(GL10.GL_PROJECTION);
//重設(shè)視圖模型變換 大猛, 用于觀測(cè)創(chuàng)建的物體.
gl.glLoadIdentity();
//個(gè)人理解 ===》即為視角 - - 不知道準(zhǔn)不準(zhǔn)
GLU.gluPerspective(gl,45,aspect,0.1f,100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
//這里會(huì)一直執(zhí)行扭倾,相當(dāng)于一個(gè)無限循環(huán)的線程
@Override
public void onDrawFrame(GL10 gl) {
//將緩存清除為預(yù)先的設(shè)置值.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0f,00f,-6f);
square.draw(gl);
}
}
繪制圖形:
public class Square {
private FloatBuffer vertexBuffer;
private ByteBuffer indexBuffer;
//這個(gè)是坐標(biāo)軸的坐標(biāo),一個(gè)條數(shù)據(jù)代表一個(gè)坐標(biāo)點(diǎn)挽绩,分別是XYZ軸的坐標(biāo)點(diǎn)
private float[] vertices={
-1.0f,-1.0f,0.0f,
1.0f,-1.0f,0.0f,
-1.0f,1.0f,0.0f,
1.0f,1.0f,0.0f
};
private byte[] indices={0,1,2};
public Square(){
//創(chuàng)建一個(gè)緩沖區(qū)吆录,長(zhǎng)度是verticesBuffer的四倍 應(yīng)為verticesBuffer 是四個(gè)字節(jié)的
ByteBuffer vbb=ByteBuffer.allocateDirect(vertices.length*4);
//定義在底層的本地平臺(tái)上的byte的順序=====》這個(gè)沒弄懂,感覺就像fragmenglayout的層級(jí)關(guān)系差不多
vbb.order(ByteOrder.nativeOrder());
//把byte類型的buff轉(zhuǎn)成Float
vertexBuffer=vbb.asFloatBuffer();
vertexBuffer.put(vertices);
//保證是從緩沖區(qū)的開頭讀取琼牧,相當(dāng)于list的第一個(gè)數(shù)據(jù)下標(biāo)
vertexBuffer.position(0);
indexBuffer=ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
}
//此方法在后面被它的實(shí)例對(duì)象調(diào)用
public void draw(GL10 gl){
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//第一個(gè)參數(shù)代表每個(gè)坐標(biāo)點(diǎn)用幾個(gè)坐標(biāo)表示(即xyz三軸)恢筝,第二個(gè)參數(shù)指坐標(biāo)軸應(yīng)當(dāng)被解析為folat類型(這樣OpenGL就可以知道每個(gè)值占用幾位)
//第三個(gè)參數(shù)可以稱為“步長(zhǎng)”,代表每個(gè)點(diǎn)之間有幾位分割巨坊。本例中撬槽,0代表一個(gè)點(diǎn)挨著一個(gè)點(diǎn),有時(shí)候你可能會(huì)在點(diǎn)的后面定義顏色趾撵,這時(shí)侄柔,你應(yīng)該指出每個(gè)顏色占用的位長(zhǎng)共啃,以便OpenGL在解析時(shí)跳過這段長(zhǎng)度.
gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,vertices.length/3);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}