前面已经简单框架搭好了,现在进行封装下一边以后更好的学习
1.我们都知道OpenGLES 呈现方式是依靠GLSurfaceView 来绘制出来的的那我们就从GLSurfaceView入手
public class FGLView extends GLSurfaceView {
private FGLRender renderer;
/*构造方法*/
public FGLView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/*初始化*/
private void init(){
/*OpenGL的版本 当前是OpenGL2*/
setEGLContextClientVersion(2);
/*这行代码是最重要的 渲染主要是Render来负责的*/
setRenderer(renderer=new FGLRender(this));
/*渲染的模式*/
/** setRenderMode(Model)
*public static final int RENDERMODE_CONTINUOUSLY = 1; 自动渲染模式
* public static final int RENDERMODE_WHEN_DIRTY = 0; 脏模式 需要渲染才进行渲染
*/
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
/*适用于多个页面切换*/
public void setShape(Class<? extends Shape> clazz){
try {
renderer.setShape(clazz);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2。第一步就相当于xml 布局文件写完了,那么现在开始写 GLSurfaceView.Renderer 里面有三个 方法
//每一帧都会去绘制
@Override
public void onDrawFrame(GL10 gl) {}
//页面有改变的时候 例如生命周期改变的时候
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {}
//开始创建
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {}
开始封装FGLRender
public class FGLRender extends Shape {
private static final String TAG = "zhangxin";
private Shape shape;
private Class<? extends Shape> clazz = Triangle.class;
/*构造方法*/
public FGLRender(View mView) {
super(mView);
}
public void setShape(Class<? extends Shape> shape) {
this.clazz = shape;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//清屏让屏幕显示的颜色
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
Log.e(TAG, "输出信息-->: onSurfaceCreated" );
try {
//不知道,抄的
Constructor constructor = clazz.getDeclaredConstructor(View.class);
constructor.setAccessible(true);
shape = (Shape) constructor.newInstance(mView);
} catch (Exception e) {
e.printStackTrace();
shape = new Triangle(mView);
}
shape.onSurfaceCreated(gl, config);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.e(TAG, "输出信息-->: onSurfaceChanged" );
//获取屏幕的大小
GLES20.glViewport(0, 0, width, height);
shape.onSurfaceChanged(gl, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
Log.e(TAG, "输出信息-->: onDrawFrame" );
//清楚深度和颜色
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
shape.onDrawFrame(gl);
}
}
加载顶点着色器和片元着色器
public abstract class Shape implements GLSurfaceView.Renderer {
protected View mView;
public Shape(View mView){
this.mView = mView;
}
public int loadShader (int type ,String shaderCode){
/*根据type创建顶点着色器或者片元着色器*/
int shader = GLES20.glCreateShader(type);
/*将资源加入着色器中编译*/
GLES20.glShaderSource(shader,shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
现在开始绘制三角形 主要呈现的就在Model3D
public class Triangle extends Shape {
private FloatBuffer vertexBuffer;
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private int mProgram;
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = {
0.5f, 0.5f, 0.0f, // top
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f // bottom right
};
private int mPositionHandle;
private int mColorHandle;
private float[] mViewMatrix=new float[16];
//顶点个数
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
//顶点之间的偏移量
private final int vertexStride = COORDS_PER_VERTEX * 4; // 每个顶点四个字节
private int mMatrixHandler;
//设置颜色,依次为红绿蓝和透明通道
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
public Triangle(View mView) {
super(mView);
ByteBuffer bb = ByteBuffer.allocateDirect(triangleCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(triangleCoords);
vertexBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
//创建一个空的OpenGLES程序
mProgram = GLES20.glCreateProgram();
//将顶点着色器加入到程序
GLES20.glAttachShader(mProgram, vertexShader);
//将片元着色器加入到程序中
GLES20.glAttachShader(mProgram, fragmentShader);
//连接到着色器程序
GLES20.glLinkProgram(mProgram);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}
@Override
public void onDrawFrame(GL10 gl) {
//将程序加入到OpenGLES2.0环境
GLES20.glUseProgram(mProgram);
//获取顶点着色器的vPosition成员句柄
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
//启用三角形顶点的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//准备三角形的坐标数据
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
//获取片元着色器的vColor成员的句柄
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
//设置绘制三角形的颜色
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//绘制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
//禁止顶点数组的句柄
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
Activity代码
public class Load3DActivity extends AppCompatActivity {
private static final String TAG = "zhangxin";
private FGLView fglView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loadopengl);
init();
}
private void init() {
fglView = (FGLView) findViewById(R.id.fglView);
}
@Override
protected void onResume() {
super.onResume();
fglView.onResume();
}
@Override
protected void onPause() {
super.onPause();
fglView.onPause();
}
}
xml文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.alvasystems.openGLes.loadshader.FGLView
android:id="@+id/fglView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>