初识OpenGL
什么是OpenGLES
“OpenGL ES是基于OpenGL三维图形API的子集,主要针对手机以及掌上电脑等嵌入式设备设计的。”简而言之,就是用来开发嵌入式设备的三维图形显示的一套API。
OpenGL10和OpenGL20的异同
网上大部分Demo都是用OpenGLES10来开发的,至于OpenGLES20有啥好处,这个回头再讲。
Android代码中如何使用OpenGL20
一句话,是通过GLSurfaceView来使用OpenGL。
具体来讲,是通过
“Activity -> GLSurfaceView -> GLSurfaceView.Render -> 构建图形”
这样的一个顺序来一步步使用OpenGLES20的接口的。
构建图形的时候,还用到了几个东西:
通过 顶点坐标矩阵 完成 图形动画变换 和 投影(物体前后关系的显示)
通过 纹理坐标矩阵 或 顶点颜色矩阵 完成 纹理映射 或 上色 ,在 着色器语言脚本 (.sh代码中)实现 光照 效果
通过 摄像机矩阵 设置观看的 视角
这里我们用到了很多矩阵。不要怕,只不过是纸老虎。大部分矩阵变换的代码是不需要我们亲自弄懂原理的,接口中已经封装好了。
而在代码例子中,矩阵变换更是已经被封装成了个工具类,直接调用即可。我们只需要关心坐标矩阵就可以了。
另外,着色器语言脚本也有点吓人。一看,是.sh文件,里面的代码和天书似的。不用怕,这个我们也不需要亲自实现。至少暂时是不需要的。
重点,我认为,是图形的构建。
下面结合一个例子来讲,是如何一步步建模,贴纹理的。
Activity中要注意的点
public class MyActivity extends Activity {
private MySurfaceView mGLSurfaceView;
static boolean threadFlag;//纹理矩形绕X轴旋转工作标志位
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//设置为全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//设置为竖屏模式
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//切换到主界面
//初始化GLSurfaceView
mGLSurfaceView = new MySurfaceView(this);
setContentView(mGLSurfaceView);
mGLSurfaceView.requestFocus();//获取焦点
mGLSurfaceView.setFocusableInTouchMode(true);//设置为可触控
}
@Override
protected void onResume() {
super.onResume();
threadFlag=true;
mGLSurfaceView.onResume();
}
@Override
protected void onPause() {
super.onPause();
threadFlag=false;
mGLSurfaceView.onPause();
}
}
自寻关键点。
GLSurfaceView和GLSurfaceView.Render中要注意的点
public class MySurfaceView extends GLSurfaceView
{
private final float TOUCH_SCALE_FACTOR = 180.0f/320;//角度缩放比例
private SceneRenderer mRenderer;//场景渲染器
private float mPreviousY;//上次的触控位置Y坐标
private float mPreviousX;//上次的触控位置X坐标
int textureId;//系统分配的纹理id
public MySurfaceView(Context context) {
super(context);
this.setEGLContextClientVersion(2); //设置使用OPENGL ES2.0
mRenderer = new SceneRenderer(); //创建场景渲染器
setRenderer(mRenderer); //设置渲染器
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染
}
//触摸事件回调方法
@Override
public boolean onTouchEvent(MotionEvent e) {
float y = e.getY();
float x = e.getX();
switch (e.getAction()) {
case MotionEvent.ACTION_MOVE:
float dy = y - mPreviousY;//计算触控笔Y位移
float dx = x - mPreviousX;//计算触控笔X位移
mRenderer.texRect.yAngle += dx * TOUCH_SCALE_FACTOR;//设置纹理矩形绕y轴旋转角度
mRenderer.texRect.zAngle+= dy * TOUCH_SCALE_FACTOR;//设置第纹理矩形绕z轴旋转角度
}
mPreviousY = y;//记录触控笔位置
mPreviousX = x;//记录触控笔位置
return true;
}
private class SceneRenderer implements GLSurfaceView.Renderer
{
Triangle texRect;//纹理矩形
public void onDrawFrame(GL10 gl)
{
//清除深度缓冲与颜色缓冲
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
//绘制纹理矩形
texRect.drawSelf(textureId);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
//设置视窗大小及位置
GLES20.glViewport(0, 0, width, height);
//计算GLSurfaceView的宽高比
float ratio = (float)