前言
今天我们通过一个OpenGL的一个简单使用案例,来看看它是如何绘制渲染到屏幕的,同时结合我们平常的iOS开发来理解一下。大致的执行图:

开始
main()
: 任何程序启动的入口,我们在这里主要做了这么几件事情:
- 初始化OpenGL环境变量
- 设置窗口大小和标题
- 注册监听回调函数(窗口大小发生改变的回调;绘制/重绘回调;键盘特殊键位点击后的的回调)
- 调用
setupRC()
,执行一些初始化工作
int main(int argc,char *argv[])
{
//设置当前工作目录,针对MAC OS X
gltSetWorkingDirectory(argv[0]);
//初始化GLUT库,这个函数只是传说命令参数并且初始化glut库
glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
//GLUT窗口大小、窗口标题
glutInitWindowSize(800, 600);
glutCreateWindow("Triangle");
//注册重塑函数,当窗口大小发生改变时,会触发changeSize()回调
glutReshapeFunc(changeSize);
//注册显示函数;当changeSize触发时,或者glutPostRedisplay()会触发
//RenderScene()回调
glutDisplayFunc(RenderScene);
//注册特殊函数(键盘按键点击监听),当点击键盘时触发;
glutSpecialFunc(SpecialKeys);
GLenum status = glewInit();
if (GLEW_OK != status) {
printf("GLEW Error:%s\n",glewGetErrorString(status));
return 1;
}
//设置我们的渲染环境
setupRC();
glutMainLoop();
return 0;
}
setupRC()
: 这里的内容完全可以放在main()
,这里单独拿出来就是为了逻辑更加清晰,这里主要做了一些初始化操作(包括背景色,类的初始化,数据构建),可以理解为UIViewController
中的viewDidLoad()
void setupRC()
{
//设置清屏颜色(背景颜色)
glClearColor(0.98f, 0.40f, 0.7f, 1);
//初始化着色管理器
shaderManager.InitializeStockShaders();
//修改为GL_TRIANGLE_FAN ,4个顶点
//其实就是在以某种方式构造数据,后面的渲染会用到这些数据
//这里用到了GLBatch批次类,是一个容器类
//装什么样的数据
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
//数据是什么
triangleBatch.CopyVertexData3f(vVerts);
//装完了
triangleBatch.End();
}
SpecialKeys()
:这是我们在main()
中添加的对键盘按钮点击后的监听回调,该回调会返回一个int 类型的key,来判断我们点击了键盘上的哪个键,监听这个方法的目的其实是为了演示屏幕上视图移动的效果,所以这里主要捕获上,下,左,右键,并做一些数据处理。
void SpecialKeys(int key, int x, int y){
GLfloat stepSize = 0.025f;
if (key == GLUT_KEY_UP) {
yPos += stepSize;
}
if (key == GLUT_KEY_DOWN) {
yPos -= stepSize;
}
if (key == GLUT_KEY_LEFT) {
xPos -= stepSize;
}
if (key == GLUT_KEY_RIGHT) {
xPos += stepSize;
}
//碰撞检测
if (xPos < (-1.0f + blockSize)) {
xPos = -1.0f + blockSize;
}
if (xPos > (1.0f - blockSize)) {
xPos = 1.0f - blockSize;
}
if (yPos < (-1.0f + blockSize)) {
yPos = -1.0f + blockSize;
}
if (yPos > (1.0f - blockSize)) {
yPos = 1.0f - blockSize;
}
//这是触发重绘的一个API,类似于调用setNeedsDisplay()
glutPostRedisplay();
}
changeSize()
: 首次加载或者窗口大小发生改变时,会触发该回调,其内部内部会触发重绘操作;
void changeSize(int w,int h)
{
//回调会返回新的w,h,通过glViewport()重新设置窗口大小,该方法内部调用了重绘操作
glViewport(0, 0, w, h);
}
RenderScene()
:这里函数主要处理的就是屏幕上具体呈现的内容,可以理解为UIView下的drawInRect:
;当changeSize()
触发后,或者调用glutPostRedisplay()
后触发该回调;
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
//设置一个颜色{R,G,B,A}
GLfloat vRed[] = {1.0f,0.0f,0.0f,0.0f};
//4x4矩阵
M3DMatrix44f mTransfromMatrix;
//平移
m3dTranslationMatrix44(mTransfromMatrix, xPos, yPos, 0.0f);
//将矩阵结果 提交给固定着色器(平面着色器)中绘制
shaderManager.UseStockShader(GLT_SHADER_FLAT,mTransfromMatrix,vRed);
triangleBatch.Draw();
//执行交换缓存区 (因为是双缓存区)
glutSwapBuffers();
}
总结
这篇文章只能针对执行过程的一个梳理,具体实现以后再说。
网友评论