OpenGL ES学习之二
来源:互联网 发布:java static修饰类 编辑:程序博客网 时间:2024/05/12 13:36
利用OpenGL ES 绘制基本图形
1. 定义形状
1.1 定义三角形
在OpenGL ES中形状的定义都是通过三维坐标(X,Y,Z)来定义的,我们一般把坐标序列先放置在一个buffer中,然后读入这个buffer。 注意点: (0,0,0)代表屏幕的中心,屏幕右上角的坐标是(1,1,0),屏幕左下角的坐标为(-1,-1,0),在书写坐标的时候按照逆时针方向来写,这个顺序比较重要,因为决定着哪些先画哪些后被画。
典型的代码如下:
public class Triangle { private FloatBuffer vertexBuffer; // number of coordinates per vertex in this array static final int COORDS_PER_VERTEX = 3; static float triangleCoords[] = { // in counterclockwise order: 0.0f, 0.622008459f, 0.0f, // top -0.5f, -0.311004243f, 0.0f, // bottom left 0.5f, -0.311004243f, 0.0f // bottom right }; // Set color with red, green, blue and alpha (opacity) values float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f }; public Triangle() { // initialize vertex byte buffer for shape coordinates ByteBuffer bb = ByteBuffer.allocateDirect( // (number of coordinate values * 4 bytes per float) triangleCoords.length * 4); // use the device hardware's native byte order bb.order(ByteOrder.nativeOrder()); // create a floating point buffer from the ByteBuffer vertexBuffer = bb.asFloatBuffer(); // add the coordinates to the FloatBuffer vertexBuffer.put(triangleCoords); // set the buffer to read the first coordinate vertexBuffer.position(0); }}
1.2 定义四边形
四边形可以通过两个三角形来定义,我们可以定义一个顶点坐标序列(四个),再定义一个绘制顶点的顺序序列。实例代码如下
public class Square { private FloatBuffer vertexBuffer; private ShortBuffer drawListBuffer; // number of coordinates per vertex in this array static final int COORDS_PER_VERTEX = 3; static float squareCoords[] = { -0.5f, 0.5f, 0.0f, // top left -0.5f, -0.5f, 0.0f, // bottom left 0.5f, -0.5f, 0.0f, // bottom right 0.5f, 0.5f, 0.0f }; // top right private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices public Square() { // initialize vertex byte buffer for shape coordinates ByteBuffer bb = ByteBuffer.allocateDirect( // (# of coordinate values * 4 bytes per float) squareCoords.length * 4); bb.order(ByteOrder.nativeOrder()); vertexBuffer = bb.asFloatBuffer(); vertexBuffer.put(squareCoords); vertexBuffer.position(0); // initialize byte buffer for the draw list ByteBuffer dlb = ByteBuffer.allocateDirect( // (# of coordinate values * 2 bytes per short) drawOrder.length * 2); dlb.order(ByteOrder.nativeOrder()); drawListBuffer = dlb.asShortBuffer(); drawListBuffer.put(drawOrder); drawListBuffer.position(0); }}
2. 绘制形状
2.1 初始化形状
如果在程序执行过程中,要绘制的图像的形状不变的话,可以先在 onSurfaceCreated()中将其初始化,这样可以预分配内存,提高执行效率
示例代码如下
public class MyGLRenderer implements GLSurfaceView.Renderer { ... private Triangle mTriangle; private Square mSquare; public void onSurfaceCreated(GL10 unused, EGLConfig config) { ... // initialize a triangle mTriangle = new Triangle(); // initialize a square mSquare = new Square(); } ...}
2.2 绘制形状的过程
绘制形状需要定义以下步骤:
- Vertex Shader: OpenGL ES中用于渲染形状顶点的代码
- Fragment Shader:OpenGL ES中绘制形状颜色和纹理的代码
Program : 用于使用shader的一个OpenGL ES对象
每一个形状都必须至少有一个Vertex Shader和一个Fragment Shader来渲染输出最后的图像,而Fragment Shader和Vertex Shader作为一段程序代码是在GPU中被编译好的。
示例代码如下
public class Triangle { 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;" + "}"; ...}
这段代码的编译规则为OpenGL Shading Language (GLSL)。如何编译它呢,我们要使用一个函数:
public static int loadShader(int type, String shaderCode){ // create a vertex shader type (GLES20.GL_VERTEX_SHADER) // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) int shader = GLES20.glCreateShader(type); // add the source code to the shader and compile it GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader;}
看来最终返回的shader是个int
我们这段shader程序的整个编译链接过程是按照如下方式进行的,值得注意的是,使用CPU编译链接这段shader程序会非常耗时,所以只编译连接一次最好
public class Triangle() { ... private final int mProgram; public Triangle() { ... int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); // create empty OpenGL ES Program mProgram = GLES20.glCreateProgram(); // add the vertex shader to program GLES20.glAttachShader(mProgram, vertexShader); // add the fragment shader to program GLES20.glAttachShader(mProgram, fragmentShader); // creates OpenGL ES program executables GLES20.glLinkProgram(mProgram); }}
总结:
总体的感觉是这样的:在vertex shader 和Fragment Shader 中写了一些变量(利用shadeing language写),然后Program链接到这两个shader中,作为一个对象,后面一直被操作。形状在准备好后,通过draw这个函数绘制,其中就要不断拿到Program这个句柄,然后把我们想要赋值的的vertex坐标和color通过句柄传进去。
- OpenGL ES学习之二
- OpenGL ES学习笔记之二
- openGL ES学习二
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- OpenGL ES之GLSurfaceView学习二:非交互式的实例
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- OpenGL ES之GLSurfaceView学习二:非交互式的实例
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- OpenGL ES之GLSurfaceView学习二:非交互式的实例
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- 从零开始学习OpenGL ES之二 – 简单绘图概述
- OpenGL ES之GLSurfaceView学习二:非交互式的实例
- OpenGL ES之GLSurfaceView学习
- 89-004-4 git标签的使用
- vue项目开发总结
- GIT服务笔记【新手】
- 由手机号绑定的账号,都应设置更换手机号功能
- Linux 进程学习(五)
- OpenGL ES学习之二
- iOS深浅拷贝
- EL表达式(函数库)
- Ubuntu 14.04 文件服务器--samba的安装和配置
- POJ 3080 Blue Jeans(暴力枚举+kmp)
- c语言-字符串去空格
- 滚动条案例
- hdu1166敌兵布阵 线段树
- Uncaught RangeError: Maximum call stack size exceeded