在弄好框架后,创建一个.hpp(或.h),内容如下:
esUtil.hpp
#ifndef ESUTIL_HPP_ #define ESUTIL_HPP_ #include <android_native_app_glue.h> #include <GLES3/gl3.h> #include <EGL/egl.h> #include <fstream> #include <string> #include "esEvent.hpp" #include "esShader.c" #include "esShapes.c" #include "esTransform.c" #include "esUtil_Android.c" #include "esUtil_win.h" #include "esUtil.c" #include "esUtil.h" #endif
esEvent.hpp(p.s.要不要无所谓,反正本章用不到)
#ifndef ESEVENT_HPP_ #define ESEVENT_HPP_ #include <android/input.h> class ESEvent { public: AInputEvent * event; public: int getX(int); int getY(int); int getType(); }; int ESEvent::getX(int n) { return AMotionEvent_getX(event,n); } int ESEvent::getY(int n) { return AMotionEvent_getY(event,n); } int ESEvent::getType() { return AInputEvent_getType(event); } #endif
弄好上述事以后,就该编写程序的框架
#include <android_native_app_glue.h> //c4droid必须要 #include "esUtil.hpp" struct UserData { GLuint id;//着色程序id }; bool init(ESContext*); void draw(ESContext*); void shutdown(ESContext*); int esMain(ESContext * esContext) { esContext->userData = new UserData; esCreateWindow ( esContext, "", 1080, 2160, ES_WINDOW_RGB );//我的手机屏幕分辨率是1080*2160的,这个根据情况而定 esRegisterShutdownFunc ( esContext, shutdown ); esRegisterDrawFunc ( esContext, draw ); if ( !init ( esContext ) ) { return 0;//表示退出 } return 1; }
当然不使用ES框架也可以,不过有些麻烦,推荐自己做一个窗口创建函数
OpenGL ES 1.0使用的渲染管线是不需要自己做的,但是从OpenGL ES 2.0开始,要开始自己制作着色器了。
如果你学习过OpenGL ES 2.0,那么可以跳过
着色器首先要声明版本
#version 300 es
GLSL(OpenGL Shading Language)的语法类似C
然后是输入数据,使用in关键字
layout(location=0)in vec3 pos;
layout(location=0)之后会讲解
vec3是一个包含3个float分量的向量,可以理解为一个包含3个元素的float数组
紧接着是main()函数
void main() { gl_Position = vec4(pos.x,pos.y,pos.z,1.0); }
gl_Position是一个内置变量,类型是vec4,我们可以用vec4构造函数赋值过去
然后程序转到下一个步骤:片段着色
同顶点着色器一样的步骤
#version 300 es out vec4 color; void main() { color = vec4(1.0,1.0,1.0,1.0); }
它要输出一个vec4作为顶点的颜色,,我们在main()中对它赋值为白色
bool init(ESContext * esContext) { UserData * ud = (UserData*)esContext->userData; char vStr[] = "#version 300 es\n" "layout(location=0)in vec3 pos;\n" "void main()\n" "{\n" " gl_Position = vec4(pos.x,pos.y,pos.z,1.0);\n" "}\n"; char fStr[] = "#version 300 es\n" "out vec4 color;\n" "void main()\n" "{\n" " color = vec4(1.0,1.0,1.0,1.0);\n" "}\n"; ud->id = esLoadProgram(vStr,fStr); if(ud->id == 0) return false; return true; }
esLoadProgram()接受两个char*作为参数,分别是顶点着色器和片段着色器,然后返回加载好后的着色程序,如果失败就是返回0
(p.s.如果你用的不是ES框架,请暂时跳到下一章,那里会讲解)
接下来是绘制
首先是顶点数组
GLfloat ver[] = { 0.0,0.5,0.0, -0.5,-0.5,0.0, 0.5,-0.5,0., };
OpenGL ES的坐标和SDL什么的不一样,是以屏幕中点为原点的,和数学里的很像(就是)
最后画出来的就长这样,一个三角形(这里的图片是640 * 480的,如果是500 * 500的应该是一个等边三角形吧)
glClearColor(0.0,0.0,0.0,0.0); //背景颜色,这里是黑色 glClear(GL_COLOR_BUFFER_BIT); //清理颜色缓冲区(???)
绘制前记得清空
glViewport ( 0, 0, esContext->width, esContext->height );
设置视口,以屏幕中心为原点,长宽分别是屏幕的长宽
没使用ES框架的可以
glQuerySurface(display,surface,EGL_WIDTH,&width); glQuerySurface(display,surface,EGL_HEIGHT,&height);
这些完成之后
glUseProgram ( ud->id ); //使用着色程序 glEnableVertexAttribArray ( 0 ); glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, ver ); //绑定顶点 glDrawArrays ( GL_TRIANGLES, 0, 3 ); //绘制 glDisableVertexAttribArray ( 0 );
其中重点讲解一下glVertexAttribPointer()函数
它的原型如下
GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
第一个参数就是顶点着色器里的
layout(location=0)in vec3 pos;
location的值
第二个是顶点分量的数量,顶点着色器里用的是vec3,那就是3
第三个是顶点类型,我们用的是
GLfloat ver[] = {...};
也就是float类型,这里写入GL_FLOAT
第四个是是否标准化,填GL_FALSE
第五个是步长,这里写入0
第六个是顶点数组,也就是ver
退出时销毁一些玩意
UserData * ud = (UserData*)esContext->userData; glDeleteProgram ( ud->id );
最后运行程序就可以了,效果如下
如果出了点问题,可以查看代码