OpenGL学习笔记——C++(待续)

摘要:
`GLUT的优先级设置以这种方式自动设置,但这种方法更安全。glutInitWindowSize;GLUT窗口大小,窗口标题glutCreateWindow;创建窗口并指定窗口名称。它设置了一个显示回调,即GLUT每次更新窗口内容时都会自动调用此例程。OpenGL中有多个缓冲区。清除缓冲区以预设值。

一、环境搭建

1、新建macOS项目;

2、添加OpenGl.framework和GLUT.framework两个系统库;

3、拖入include和libGLTool.a文件,libGLTools.a直接拖到工程的Frameworks文件里面;

4、删除AppDelegate.h,AppDelegate.m,main.m,ViewController.h,ViewController.m 文件;

5、创建main.cpp文件。(创建c++ File,去掉创建头文件的勾,同时输入文件名"main");

二、学习相关基础知识

  • gltSetWorkingDirectory(argv[0]);

设置当前工作目录,针对MAC OS X。`GLTools`函数`glSetWorkingDrectory`用来设置当前工作目录。实际上在Windows中是不必要的,因为工作目录默认就是与程序可执行执行程序相同的目录。但是在Mac OS X中,这个程序将当前工作文件夹改为应用程序捆绑包中的`/Resource`文件夹。`GLUT`的优先设定自动进行了这个中设置,但是这样中方法更加安全。

  • glutInit(&argc, (char **)argv);  

初始化一个GLUT库。

  • glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);

初始化双缓冲窗口,其中标志GLUT_DOUBLE、GLUT_RGBA、GLUT_DEPTH、GLUT_STENCIL分别指双缓冲窗口、RGBA颜色模式、深度测试、模板缓冲区

--GLUT_DOUBLE`:双缓存窗口,是指绘图命令实际上是离屏缓存区执行的,然后迅速转换成窗口视图,这种方式,经常用来生成动画效果;

--GLUT_DEPTH`:标志将一个深度缓存区分配为显示的一部分,因此我们能够执行深度测试;

--GLUT_STENCIL`:确保我们也会有一个可用的模板缓存区。

  • glutInitWindowSize(800, 600);

GLUT窗口大小、窗口标题

  • glutCreateWindow("YYT_Window");

创建一个窗口并制定窗口名。

  • glutReshapeFunc(changeSize);

注册重塑函数

// 在窗口大小改变时,接收新的宽度&高度。

void changeSize(int w,int h){

// x,y 参数代表窗口中视图的左下角坐标,而宽度、高度是像素为表示,通常x,y 都是为0

glViewport(0, 0, w, h);

}

  • glutDisplayFunc(RenderScene);

注册一个绘图函数,操作系统在必要时刻就会对窗体进行重绘制操作。它设置了一个显示回调(diplay callback),即GLUT在每次更新窗口内容的时候回自动调用该例程。

void RenderScene(void){

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

GLfloat vRed[] = {1.0,0.0,0.0,1.0f};

shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);

triangleBatch.Draw();

glutSwapBuffers();

}

  • glutSpecialFunc(SpecialKeys);

注册特殊函数

void SpecialKeys(int key, int x, int y){

if (key == GLUT_KEY_UP) {

//向上的操作,更新vVerts中各顶点的坐标数据

...

}

if (key == GLUT_KEY_DOWN) {

//向下的操作,更新vVerts中各顶点的坐标数据

...

}

if (key == GLUT_KEY_LEFT) {

//向左的操作,更新vVerts中各顶点的坐标数据

...

}

if (key == GLUT_KEY_RIGHT) {

//向右的操作,更新vVerts中各顶点的坐标数据

...

}

triangleBatch.CopyVertexData3f(vVerts);

glutPostRedisplay();

}

  • glewInit();

初始化一个GLEW库,确保OpenGL API对程序完全可用。在试图做任何渲染之前,要检查确定驱动程序的初始化过程中没有任何问题。

GLenum status = glewInit();

if (GLEW_OK != status) {

printf("GLEW Error:%s ",glewGetErrorString(status));

return 1;

}

  • glutMainLoop();

这是一个无限执行的循环,它会负责一直处理窗口和操作系统的用户输入等操作。(注意:不会执行在glutMainLoop()之后的所有命令。)

  • glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

设置清屏颜色(背景颜色),红、绿、蓝、透明度。在windows 颜色成分取值范围:0-255之间,在iOS、OS 颜色成分取值范围:0-1之间浮点值。

  • glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

清除一个或者一组特定的缓存区,缓冲区是一块存在图像信息的储存空间,红色、绿色、蓝色和alpha分量通常一起分量通常一起作为颜色缓存区或像素缓存区引用。OpenGL 中不止一种缓冲区(颜色缓存区、深度缓存区和模板缓存区),清除缓存区对数值进行预置。参数:指定将要清除的缓存区的遮罩的按位或运算。

GL_COLOR_BUFFER_BIT: 指示当前激活的用来进行颜色写入缓存区

GL_DEPTH_BUFFER_BIT:指示深度缓存区

GL_STENCIL_BUFFER_BIT:指示模板缓存区

错误:如果设定不是以上三个参考值,返回GL_INVALID_VALUE

  • glColor3f(1.0f, 0.0f, 0.0f);

设置颜色

  • glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);

设置绘图是的坐标系统,左、右、上、下、近、远

  • glBegin(GL_POLYGON);

开始渲染

  • 设置顶点

glVertex2f(x, y);

glVertex3f(x, y, z);

  • glEnd();

结束渲染

  • glFlush();

强制刷新缓存区,保证绘制命令得以执行

  • 复杂图形可以由很多小线段组成

(1)、画圆:

const int n = 55;//当n为3时为三角形;n为4时是四边形,n为5时为五边形。。。。。

const GLfloat R = 0.5f;//圆的半径

const GLfloat pi = 3.1415926f;

for (int i = 0; i < n; i++) {

glVertex2f(R*cos(2 * pi / n*i), R*sin(2 * pi / n*i));

}

(2)、画五角星:

设五角星的五个顶点分布位置关系如下:

A

E   B

D C

首先,根据余弦定理列方程,计算五角星的中心到顶点的距离a,然后,根据正弦和余弦的定义,计算B的x坐标bx和y坐标by,以及C的y坐标。(假设五角星的中心在坐标原点)

bx = a * cos(18 * Pi/180);

by = a * sin(18 * Pi/180);

cy = -a * cos(18 * Pi/180);

五个点的坐标就可以通过以上四个量和一些常数简单的表示出来

const GLfloat Pi = 3.1415926536f;

GLfloat a = 1 / (2-2*cos(72*Pi/180));

GLfloat bx = a * cos(18 * Pi/180);

GLfloat by = a * sin(18 * Pi/180);

GLfloat cy = -a * cos(18 * Pi/180);

GLfloat

PointA[2] = { 0, a },

PointB[2] = { bx, by },

PointC[2] = { 0.5, cy },

PointD[2] = { -0.5, cy },

PointE[2] = { -bx, by };

glClear(GL_COLOR_BUFFER_BIT);

// 按照A->C->E->B->D->A的顺序,可以一笔将五角星画出

glBegin(GL_LINE_LOOP);

glVertex2fv(PointA);

glVertex2fv(PointC);

glVertex2fv(PointE);

glVertex2fv(PointB);

glVertex2fv(PointD);

glEnd();

glFlush();

(3)、画出正弦函数的图形---------------

由于OpenGL默认坐标值只能从-1到1,(可以修改)。所以我们设置一个因子factor,把所有的坐标值等比例缩小,这样就可以画出更多个正弦周期,试修改factor的值,观察变化情况

const GLfloat factor = 0.1f;

GLfloat x;

glClear(GL_COLOR_BUFFER_BIT);

glBegin(GL_LINES);

glVertex2f(-1.0f, 0.0f);

glVertex2f(1.0f, 0.0f); // 以上两个点可以画x轴

glVertex2f(0.0f, -1.0f);

glVertex2f(0.0f, 1.0f); // 以上两个点可以画y轴

glEnd();

glBegin(GL_LINE_STRIP);

for(x=-1.0f/factor; x<1.0f/factor; x+=0.01f)

{

glVertex2f(x*factor, sin(x)*factor);

}

glEnd();

glFlush();

  • GLShaderManager shaderManager;

定义一个,着色管理器。GLShaderManager.h 中移入了GLTool 着色器管理器(shader Mananger)类。没有着色器,我们就不能在OpenGL(核心框架)进行着色。着色器管理器不仅允许我们创建并管理着色器,还提供一组“存储着色器”,他们能够进行一些初步的基本的渲染操作。

  • shaderManager.InitializeStockShaders();

没有着色器,在OpenGL 核心框架中是无法进行任何渲染的。初始化一个渲染管理器。

//设置一组浮点数来表示红色

GLfloat vRed[] = {1.0,0.0,0.0,1.0f};

//传递到存储着色器,即GLT_SHADER_IDENTITY着色器,这个着色器只是使用指定颜色以默认笛卡尔坐标第在屏幕上渲染几何图形

shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);

  • GLBatch triangleBatch;

简单的批次容器,是GLTools的一个简单的容器类。

//指定顶点,每三个表示一个点,在OpenGL中,三角形是一种基本的3D图元绘图原素。

GLfloat vVerts[] = {

-0.5f,0.0f,0.0f,

0.5f,0.0f,0.0f,

0.0f,0.5f,0.0f

};

triangleBatch.Begin(GL_TRIANGLES, 3);

triangleBatch.CopyVertexData3f(vVerts);

triangleBatch.End();

//提交着色器

triangleBatch.Draw();

  • glutSwapBuffers();

在开始的设置openGL 窗口的时候,我们指定要一个双缓冲区的渲染环境。这就意味着将在后台缓冲区进行渲染,渲染结束后交换给前台。这种方式可以防止观察者看到可能伴随着动画帧与动画帧之间的闪烁的渲染过程。缓冲区交换平台将以平台特定的方式进行。将后台缓冲区进行渲染,然后结束后交换给前台。

免责声明:文章转载自《OpenGL学习笔记——C++(待续)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ubuntu日志的设置V4L2驱动的移植与应用(二)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

简单基于OPENGL的三维CAD框架(1)工具类

在vc++中有CDC类,同样也可以开发基于OPENGL的OPenGLDC类,这样可以像调用CDC类一样调用OPenGLDC类 首先给出两个工具类,点类和向量类 typedef struct tagVector3D {double dx;double dy;double dz;} VECTOR3D; class CVector3D : public VECT...

openGL 函数 收集

glViewport()函数 在OpenGL初始化完成之后,我们应该进行一些视图设置。首先是设定视见区域,即告诉OpenGL应把渲染之后的图形绘制在窗体的哪个部位。当视见区域是整个窗体时,OpenGL将把渲染结果绘制到整个窗口。我们调用glViewPort函数来决定视见区域: procedureglViewPort(x:GLInt;y:GLInt;Widt...

OpenGL的glViewport视口变换函数详解[转]

调用glViewPort函数来决定视见区域,告诉OpenGL应把渲染之后的图形绘制在窗体的哪个部位。当视见区域是整个窗体时,OpenGL将把渲染结果绘制到整个窗口。 voidglViewPort(GLInt x; GLInty; GLSizeiWidth; GLSizeiHeight);     其中,参数X,Y指定了视见区域的左下角在窗口中的位置,一般情...

Qt OpenGL 2D图像文字

这次教程中,我们将学会如何使用四边形纹理贴图把文字显示在屏幕上。我们将把256个不同的文字从一个256×256的纹理图像中一个个提取出来,接着创建一个输出函数来创建任意我们希望的文字。 还记得在第一篇字体教程中我提到使用纹理在屏幕上绘制文字吗?通常当你使用纹理绘制文字时你会调用你最喜欢的图像处理程序,选择一种字体,然后输入你想显示的文字或段落,然后保存下来...

[osg][opengl]透视投影的参数Perspective

gluPerspective这个函数指定了观察的视景体(frustum为锥台的意思,通常译为视景体)在世界坐标系中的具体大小,一般而言,其中的参数aspect应该与窗口的宽高比大小相同。比如说,aspect=2.0表示在观察者的角度中物体的宽度是高度的两倍,在视口中宽度也是高度的两倍,这样显示出的物体才不会被扭曲。 gluPerspective NAME...

OpenGL实现多层绘制(Layered Rendering) [转]

http://blog.csdn.net/u010462297/article/details/50589991 引言 在某些情况下会需要用到多层绘制。FBO下有多个颜色挂接点(Color Attachment),可以用不同的挂接点挂接不同的纹理对象,实现绘制多张纹理(MRT),这在之前的文章里已经有所描述。但是有时候这种方法是不够好用的: - 当纹理非...