三角形
triangles:三角形集
triangle_strip:三角形带(用的最多)
triangle_fan:扇面
顶点着色模式:
1.smooth:平滑模式(渐变过渡)。默认。
2.flat:单调(跟最后一个点的颜色相同)。
深度轴:z轴
深度缓冲区:每个像素的深度值。
深度测试:启用z值,被遮挡的物体看不见。
剔除:如果看不见的部分,告诉openGL不要绘图,提高性能。
public class MyActivity extends Activity {
private MyRenderer render;
private MyGLSurfaceView view;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = new MyGLSurfaceView(this);
render = new MyRenderer();
view.setRenderer(render);
view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);// 脏渲染,命令渲染
setContentView(view);
}
class MyGLSurfaceView extends GLSurfaceView {
public MyGLSurfaceView(Context context) {
super(context);
}
public MyGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
class MyRenderer implements GLSurfaceView.Renderer {
private float ratio, xrotate, yrotate;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// 清屏色
gl.glClearColor(0f, 0f, 0f, 1f);
// 启用顶点缓冲区
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 启用颜色缓冲区
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// 设置视口
gl.glViewport(0, 0, width, height);
ratio = (float) width / (float) height;
// 投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
// 加载单位矩阵
gl.glLoadIdentity();
// 设置平截头体
gl.glFrustumf(-ratio, ratio, -1, 1, 3f, 7f);
}
@Override
public void onDrawFrame(GL10 gl) {
// 清除颜色缓冲区和深度缓冲区
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 设置绘图颜色
gl.glColor4f(1f, 0f, 0f, 1f);
// 启用深度测试;否则最后绘制底面的始终显示,不管是否被遮挡,总能看见!
gl.glEnable(GL10.GL_DEPTH_TEST);
// 启用表面剔除
gl.glEnable(GL10.GL_CULL_FACE);
// CCW:counter clock wise-->逆时针
// CW:clock wise--> 顺时针
gl.glFrontFace(GL10.GL_CCW);// 指定逆时针为正面(锥面是逆时针绘制的)
// 剔除背面(圆锥体里面)
gl.glCullFace(GL10.GL_BACK);
// GL10.GL_SMOOTH:平滑着色(默认)
// GL10.GL_FLAT:单调模式着色
gl.glShadeModel(GL10.GL_FLAT);
// 操作模型视图矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
// 设置眼球的参数
GLU.gluLookAt(gl, 0f, 0f, 5f, 0f, 0f, 0f, 0f, 1f, 0f);
// 旋转角度
gl.glRotatef(xrotate, 1, 0, 0);
gl.glRotatef(yrotate, 0, 1, 0);
// 计算点坐标
float r = 0.5f;// 半径
float x = 0f, y = 0f, z = -0.5f;
/******************** 锥面 ************************/
// 顶点坐标集合
List<Float> coordsList = new ArrayList<Float>();
// 添加锥顶点
coordsList.add(0f);
coordsList.add(0f);
coordsList.add(0.5f);
// 顶点颜色集合
List<Float> colorList = new ArrayList<Float>();
colorList.add(1f);// r
colorList.add(0f);// g
colorList.add(0f);// b
colorList.add(1f);// a
/******************** 锥底 ************************/
// 锥底坐标
List<Float> coordsConeBottomList = new ArrayList<Float>();
coordsConeBottomList.add(0f);
coordsConeBottomList.add(0f);
coordsConeBottomList.add(-0.5f);
boolean flag = false;
// 底面
for (float alpha = 0f; alpha < Math.PI * 6; alpha += (float) (Math.PI / 8)) {
// 锥面
x = (float) (r * Math.cos(alpha));
y = (float) (r * Math.sin(alpha));
coordsList.add(x);
coordsList.add(y);
coordsList.add(z);
// 锥底坐标
coordsConeBottomList.add(x);
coordsConeBottomList.add(y);
coordsConeBottomList.add(z);
// 点颜色值
if (flag = !flag) {
// 黄色
colorList.add(1f);
colorList.add(1f);
colorList.add(0f);
colorList.add(1f);
} else {
// 红色
colorList.add(1f);
colorList.add(0f);
colorList.add(0f);
colorList.add(1f);
}
}
// 在颜色缓冲区增加一个颜色
if (flag = !flag) {
// 黄色
colorList.add(1f);
colorList.add(1f);
colorList.add(0f);
colorList.add(1f);
} else {
// 红色
colorList.add(1f);
colorList.add(0f);
colorList.add(0f);
colorList.add(1f);
}
// 颜色缓冲区
ByteBuffer colorBuffer = list2ByteBuffer(colorList);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
// 绘制锥面
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, list2ByteBuffer(coordsList));
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, coordsList.size() / 3);
// 锥底也是逆时针绘制,是从锥体里面绘制的,所以要剔除正面,留背面(即外底表面可视表面)
gl.glCullFace(GL10.GL_FRONT);
// 绘制锥底
colorBuffer.position(4 * 4);//单位:字节(字节缓冲区),定位到:4个分量×floatSize,即下一个颜色
//如果是浮点缓冲区,则position()参数值为4.
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, list2ByteBuffer(coordsConeBottomList));
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, coordsConeBottomList.size() / 3);
}
}
private ByteBuffer list2ByteBuffer(List<Float> list) {
ByteBuffer ibb = ByteBuffer.allocateDirect(list.size() * 4);
ibb.order(ByteOrder.nativeOrder());
FloatBuffer fbb = ibb.asFloatBuffer();
for (Float f : list) {
fbb.put(f);
}
ibb.position(0);
return ibb;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
float step = 5f;
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
render.xrotate -= step;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
render.xrotate += step;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
render.yrotate += step;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
render.yrotate -= step;
}
// 请求渲染,和脏渲染配合使用
view.requestRender();
return super.onKeyDown(keyCode, event);
}
}