Android学习日记(yzy):opengl 绘制2d图形 基本框架

时间:2022-03-04 12:10:05



首先,要了解opengl 在android中只有三种绘制方式-点,线,和三角形。

点的描绘方式:GL_POINTS

线的描绘方式:
GL_LINES(每两个顶点作为独立的线)
GL_LINE_STRIF(从第0个顶点到最后一个顶点依次相连)

GL_LINE_LOOP(从第0个顶点到最后一个顶点依次相连,最后一个顶点连接初始顶点)


三角形的绘制方式:
GL_TRIANGLES(
每三个顶点形成三角形)
GL_TRIANGLES_STRIP(
n,n+1,n+2 依次连接的顶点形成的 所有三角形)
GL_TRIANGLES_FAN (以第0个顶点确定,其余两个顶点依次
为n,n+1来绘制三角形 )


在绘制图像时,首先建一个类定义创建的图形形状。


第一步骤: float verticesArray 确定顶点, short indicesArray (索引)确定顺序。

第二步骤: 创建类如:Square(){}来缓冲数据;
ByteBuffer vbb = ByteBuffer.allocateDirect(verticesArray.length * 4)开辟新的累存块
vbb.order(ByteOrder.nativeOrder())
FloatBuffer vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);放入索引坐标数据
vertexBuffer.position(0);起始位置设定

第三步骤: 创建方法来构造形状
draw( GL10 gl )-->
gl.glColor4f(1.0f,0.0f,0.0f,1.0f);设置颜色
   gl.glTranslatef(0.1f,0,-2.0f);创建的形状初始坐标
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);采用顶点坐标数组
gl.glVertexPointer(3//坐标数,GL10.GL_FIXED,0,vertexBuffer//顶点坐标缓冲 )指定顶点坐标数据
gl.glDrawElement(绘制方式,indicesArray.length//索引数,GL10.GL_UNSIGNED_SHORT//,索引缓冲)绘制图像

public class Square {
private float vertices[] = {
-0.1f, 0.1f, 0.0f,
-0.1f, -0.1f, 0.0f,
0.1f, -0.1f, 0.0f,
0.1f, 0.1f, 0.0f,
};

private short[] indices = {0, 1, 2, 0, 2, 3};

private FloatBuffer vertexBuffer;
private ShortBuffer indexBuffer;

public Square() {

ByteBuffer v_byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
v_byteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = v_byteBuffer.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);

ByteBuffer i_byteBuffer = ByteBuffer.allocateDirect(indices.length * 2);
i_byteBuffer.order(ByteOrder.nativeOrder());
indexBuffer = i_byteBuffer.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}

public void draw(GL10 gl) {
gl.glColor4f(0.8f,0.0f,0.0f,1.0f);
// gl.glLoadIdentity();
gl.glTranslatef(0.1f,0,-2.0f);
// gl.glFrontFace(GL10.GL_CCW);
// gl.glEnable(GL10.GL_CULL_FACE);
// gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0,
vertexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
// gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
// gl.glDisable(GL10.GL_CULL_FACE);

其次,再创建接口类(GLSurfaceView.Renderer)作为你要放入图像的画布。

重写方法:onSurefaceCreated,onDrawFrameonSurfaceChanged


第一步骤:onSurefaceCreated(GL10 gl,EGLConfig config){
gl.glShadeModel(GL10.GL_SMOOTH);抗锯齿
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_NICEST);Hind模式
gl.glClearColor(0.0f,0.8f,0.0f,0.5f);桌布颜色
gl.glClearDepthf(1.0f);深度清理缓存
}


第二步骤:onDrawFrame(GL10 gl){
将之前描绘的图形初始化
  gl.glClear(GL10.GL_COLOR_BUFFER_BIT| GL10.GL_DEPTH_BUFFER_BIT);清理缓存
  gl.glLoadIdentity()设置当前矩阵为单位矩阵
  gl.glPushMatrix();
     
      drawLine.draw(gl);绘制图像
     
     gl.glPopMatrix();

}

第三步骤:onSurfaceChanged(GL10 gl,int width,int height){
gl.glViewport(0,0,width,height)设置视图
gl.glMatrixMode(GL10.GL_PROJECTION);设置为投影矩阵
gl.glLoadIdentity()设置当前矩阵为单位矩阵
GLU.gluPerspective(gl,45.0f,(float)width/(float)height,0.1f,100.0f);
     
         gl.glMatrixMode(GL10.GL_MODELVIEW);
     
          gl.glLoadIdentity();
}

public class MyRenderer implements GLSurfaceView.Renderer {
Drawcub drawcub;
public void onSurfaceCreated(GL10 gl, EGLConfig config){
gl.glShadeModel(GL10.GL_SMOOTH);//抗锯齿
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_NICEST);//Hind模式
gl.glClearColor(0.0f,0.0f,0.2f,0.5f);//桌布颜色
gl.glClearDepthf(1.0f);//深度清理缓存
}
public void onDrawFrame(GL10 gl){

Square square = new Square();
DrawPoint drawPoint = new DrawPoint();
DrawLine drawLine = new DrawLine();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT
| GL10.GL_DEPTH_BUFFER_BIT);
// Replace the current matrix with the identity matrix
gl.glLoadIdentity();
gl.glPushMatrix();
// square.draw(gl);
drawcub.drawSelf(gl);
gl.glPopMatrix();
}
public void onSurfaceChanged(GL10 gl,int width,int height){
gl.glViewport(0,0,width,height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl,45.0f,(float)width/(float)height,0.1f,100.0f);
drawcub = new Drawcub(0,0,0,3,(float)width/(float)height);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();

}



最后setContentView将初始化的GLSrefaceView(),放入activity中。


public class SceneRenderer implements GLSurfaceView.Renderer {
Drawcub drawcub;
public void onSurfaceCreated(GL10 gl, EGLConfig config){
gl.glShadeModel(GL10.GL_SMOOTH);//抗锯齿
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_NICEST);//Hind模式
gl.glClearColor(0.0f,0.0f,0.2f,0.5f);//桌布颜色
gl.glClearDepthf(1.0f);//深度清理缓存
}
public void onDrawFrame(GL10 gl){

Square square = new Square();
DrawPoint drawPoint = new DrawPoint();
DrawLine drawLine = new DrawLine();
gl.glClear(GL10.GL_COLOR_BUFFER_BIT
| GL10.GL_DEPTH_BUFFER_BIT);
// Replace the current matrix with the identity matrix
gl.glLoadIdentity();
gl.glPushMatrix();
// square.draw(gl);
drawcub.drawSelf(gl);
gl.glPopMatrix();
}
public void onSurfaceChanged(GL10 gl,int width,int height){
gl.glViewport(0,0,width,height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl,45.0f,(float)width/(float)height,0.1f,100.0f);
drawcub = new Drawcub(0,0,0,3,(float)width/(float)height);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();

}

续写,写了一个好玩的东西。

MainActivity:

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
GLSurfaceView view = new GLSurfaceView(this);
view.setRenderer(new MyRenderer());
setContentView(view);
}
}
MyRenderer:

public class MyRenderer implements GLSurfaceView.Renderer {

float positionX =0;
float positionY =0;
float positionZ =0;
float length = 0.5f;
float distance = 5;
private float angle;

Cube cube = new Cube(positionX,positionY,positionZ,length);
SquareTest squareTest = new SquareTest();
boolean flag =true;

public void onSurfaceCreated(GL10 gl, EGLConfig config){
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glShadeModel(GL10.GL_SMOOTH);
//add
gl.glClearDepthf(1.0f);// OpenGL docs.
// Enables depth testing.
gl.glEnable(GL10.GL_DEPTH_TEST);// OpenGL docs.
// The type of depth testing to do.
gl.glDepthFunc(GL10.GL_LEQUAL);// OpenGL docs.
// Really nice perspective calculations.
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, // OpenGL docs.
GL10.GL_NICEST);
}


public void onDrawFrame(GL10 gl){

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(positionX ,positionY, positionZ-distance);
gl.glPushMatrix();
gl.glRotatef(angle, 5, 5, 5);
// square.onDraw(gl);
cube.onDraw(gl);
gl.glPopMatrix();
gl.glPushMatrix();

DynamicPicture();

}
private void DynamicPicture(){
angle++;
if (flag == true){
distance = distance+ 0.02f;
if (distance>=12){
flag = false;
}
}else if (flag ==false){
distance = distance-0.02f;
if(distance<=6){
flag =true;
}
}
}


public void onSurfaceChanged(GL10 gl,int width, int height){
gl.glViewport(0,0,width,height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl,45.0f,(float)width/(float)height,0.1f,100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}

}

Cube:

public class Cube {

FloatBuffer verticesBuffer;
ShortBuffer indexBuffer;
int verticesCount ;
int indexCount;
public Cube(float positionX,float positionY,float positionZ, float length){

float vertices[] = {
positionX-length,positionY-length,positionZ-length,
-(positionX-length),positionY-length,positionZ-length,
-(positionX-length),-(positionY-length),positionZ-length,
positionX-length,-(positionY-length),positionZ-length,

positionX-length,positionY-length,-(positionZ-length),
-(positionX-length),positionY-length,-(positionZ-length),
-(positionX-length),-(positionY-length),-(positionZ-length),
positionX-length,-(positionY-length),-(positionZ-length),
};


short index[]={
0,1,1,2,2,3,3,0,
4,5,5,6,6,7,7,4,
0,4,1,5,2,6,3,7
};

ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
verticesBuffer = vbb.asFloatBuffer();
verticesBuffer.put(vertices);
verticesBuffer.position(0);
//
ByteBuffer ibb = ByteBuffer.allocateDirect(index.length*2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(index);
indexBuffer.position(0);

verticesCount = vertices.length;
indexCount = index.length;
}


public void onDraw(GL10 gl){

gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0,verticesBuffer);//GL_FLOAT
gl.glDrawElements(GL10.GL_LINES, indexCount, GL10.GL_UNSIGNED_SHORT, indexBuffer);

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
}