OpenGL 是一个非常底层的画图接口,它所使用的缓冲区存储结构是和我们的 java 程序中不相同的。
Java 是大端字节序(BigEdian),而 OpenGL 所需要的数据是小端字节序(LittleEdian)。 所以,我们在将 Java 的缓冲区转化为 OpenGL 可用的缓冲区时需要作一些工作。
建立buff的方法如下:
class BufferUtil {
public static FloatBuffer mBuffer;
public static IntBuffer mBuffer2;
public static FloatBuffer floatToBuffer(float[] a) {
//先初始化buffer,数组的长度*4,因为一个float占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);
//数组排序用nativeOrder
mbb.order(ByteOrder.nativeOrder());
mBuffer = mbb.asFloatBuffer();
mBuffer.put(a);
mBuffer.position(0);
return mBuffer;
}
public static IntBuffer intToBuffer(int[] a) {
//先初始化buffer,数组的长度*4,因为一个float占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);
//数组排序用nativeOrder
mbb.order(ByteOrder.nativeOrder());
mBuffer2 = mbb.asIntBuffer();
mBuffer2.put(a);
mBuffer2.position(0);
return mBuffer2;
}
}
该类的2个方法可以将点的坐标转化为opengl的存储结构。
openglSurfaceView提供了图形渲染接口Render,实现该接口里的3个方法就可以显示我们要画的显示的图形纹理。线面给出最简单的一个绘图demo。
Activity和GLRender 2个java文件:
public class MainActivity extends AppCompatActivity {
private GLSurfaceView glSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
private void init() {
glSurfaceView=new GLSurfaceView(this);
GLSurfaceView.Renderer renderer=new GLRender();
glSurfaceView.setRenderer(renderer);
setContentView(glSurfaceView);
}
package com.example.zp.myapplication;
import android.opengl.GLSurfaceView;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/*
* OpenGL 是一个非常底层的画图接口,它所使用的缓冲区存储结构是和我们的 java 程序中不相同的。
* Java 是大端字节序(BigEdian),而 OpenGL 所需要的数据是小端字节序(LittleEdian)。
* 所以,我们在将 Java 的缓冲区转化为 OpenGL 可用的缓冲区时需要作一些工作。建立buff的方法如下
* */
class BufferUtil {
public static FloatBuffer mBuffer;
public static IntBuffer mBuffer2;
public static FloatBuffer floatToBuffer(float[] a) {
//先初始化buffer,数组的长度*4,因为一个float占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);
//数组排序用nativeOrder
mbb.order(ByteOrder.nativeOrder());
mBuffer = mbb.asFloatBuffer();
mBuffer.put(a);
mBuffer.position(0);
return mBuffer;
}
public static IntBuffer intToBuffer(int[] a) {
//先初始化buffer,数组的长度*4,因为一个float占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);
//数组排序用nativeOrder
mbb.order(ByteOrder.nativeOrder());
mBuffer2 = mbb.asIntBuffer();
mBuffer2.put(a);
mBuffer2.position(0);
return mBuffer2;
}
}
/**
* Created by lenovo on 2016/7/22.
*/
public class GLRender implements GLSurfaceView.Renderer {
float rotateSpeed =5* (float) Math.PI/18;
float rotateTri = 0;
int one=0x10000;
float a=0.2f;
public IntBuffer getIntTriggerBuffer(int [] a)
{
return BufferUtil.intToBuffer(a);
}
public FloatBuffer getFloatTriggerBuffer(float[] mTriangleArray)
{
return BufferUtil.floatToBuffer(mTriangleArray);
}
@Override
public void onDrawFrame(GL10 gl)
{
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();//这个是重置模型矩阵,即作图原点回到(0,0,0)
gl.glTranslatef(0f,0f,-3f);移到作图原点到(0,0,)
gl.glRotatef(rotateTri, 1.0f, 0.0f, 0.0f);
int[] quater=new int[]{
0,one,0,
-one,-one,one,
one,-one,one,
0,one,0,
one,-one,one,
one,-one,-one,
0,one,0,
one,-one,-one,
-one,-one,-one,
0,one,0,
-one,-one,-one,
-one,-one,one,
};
//设置点可用
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 这里的GL10.GL_FIXED是整形数据,即one的大小是投影在第一层时候观察的大小,显示为整个openglsurfaceview的控件中宽的大小// 当为folat类型数据时候,1代表的屏幕宽度
gl.glVertexPointer(3,GL10.GL_FIXED,0,getIntTriggerBuffer(quater));
for(int i = 0; i < 4 ; i ++)
{
if(i==0) gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
if(i==1) gl.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
if(i==2) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
if(i==3) gl.glColor4f(1.0f, 0.0f, 1.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,i*3,3);
}
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
rotateTri = rotateSpeed+rotateTri;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//告知系统对透视进行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
//设置背景为黑色
gl.glClearColor(0, 0, 0, 0);
//启用阴影平滑
gl.glShadeModel(GL10.GL_SMOOTH);
//设置深度缓存
gl.glClearDepthf(1.0f);
//启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
//所做深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
float ratio = (float) width / height;
//设置OpenGL场景的大小
gl.glViewport(0, 0, width, height);
//设置投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
//重置投影矩阵
gl.glLoadIdentity();
// 设置视口的大小
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
// 选择模型观察矩阵,这个模型只能看到第二层,既当你绘图投影在第一层时候什么都看不到,暂时没有深入研究
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置模型观察矩阵
gl.glLoadIdentity();
}
}
实现效果是个在旋转的四棱锥