刚开始接触OpenGL,有点小激动,终于绘制出一个图形了,哇
通过绘制,大概明白OpenGL的框架。主要掌握的是这个。
通过代码加注释理解程序,简单粗暴。
<span style="font-size:18px;"><span style="font-size:18px;">#include<windows.h>
#include<gl/glut.h>
#include<gl/gl.h>
#include<gl/glu.h>
//头文件/表示在gl目录下的.h头文件
//函数用于在窗口中绘制需要的图形
//只是一个场景scene 并不会真正绘制到图形中去。
void RenderScene(void)
{
//用当前清除颜色缓冲区,即设定窗口的背景颜色
// 清除viewport的缓冲区
//大概就是清除下面所要画的区域的缓冲区
glClear(GL_COLOR_BUFFER_BIT);
//设置当前绘图使用的GGB颜色 red
glColor3f(1.0f,0.0f,0.0f);
//使用当前的颜色绘制一个填充的矩形
//绘制矩形,窗口坐标系是左下角(0,0),x向右,y向上
//qt使用的是右上角(0,0)
glRectf(100.0f,150.0f,150.0f,100.0f);
//强制刷新OpenGL命令队列
glFlush();
/*
简单地说glFlush()就是强制刷新,OpenGL是使用一条渲染管线[3] 线性处理命令的,一般情况下,
我们提交给OpenGL的指令并不是马上送到驱动程序[4] 里执行的,而是放到一个缓冲区里面,
等这个缓冲区满了再一次过发到驱动程序里执行;很多时候只有几条指令是填充不满那个缓冲区的,
就是说这些指令根本没有被发送到驱动里,所以我们要调用glFlush来强制把这些指令送到驱动里进行处理。
*/
}
//函数ChangeSize是窗口大小改变时调用的登记函数
//GLsizeiGLsizei 是32位整数
void ChangeSize(GLsizei w, GLsizei h)
{
//窗口的高度y不为0
//去掉调试之后,还没发现有什么区别
if (h == 0)
h = 1;
//定义视区并指明尺寸
//一般是充满整个屏幕
glViewport(0,0,w,h);
/*
glMatrixMode设置当前矩阵模式:
GL_MODELVIEW, 对模型视景矩阵堆栈应用随后的矩阵操作.
GL_PROJECTION, 对投影矩阵应用随后的矩阵操作.
GL_TEXTURE, 对纹理矩阵堆栈应用随后的矩阵操作.
与glLoadIdentity()一同使用
glLoadIdentity():将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作
*/
//重置坐标系统,使投影变换复位
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//建立修建空间的范围
//glOrtho是在3D笛卡儿坐标空间定义
if (w <= h)
glOrtho(0.0f, 250.0f, 0.0f, 250.0f*h / w, 1.0f, -10.f);
else
glOrtho(0.0f, 250.0*w/h, 0.0f, 250.0f, 1.0f, -1.0f);
//告诉OpenGL将来的所有变换都会影响模型
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//函数setupRC用于初始化,常用来设置场景渲染状态
void SetupRC(void)
{
//这个函数用于设置清除窗口时使用的颜色,即设定窗口内的背景颜色
//最后一个参数是alpha,主要用于混合的特殊效果,如半透明效果等
//其实就是使用某种颜色 清空当前的所有颜色,或者说填充整个窗口
glClearColor(0.0f,1.0f,0.0f,1.0f);
}
//主函数基本都是glut的框架
void main(void )
{
//初始化GLUT库OpenGL窗口的显示模式
//glutInitDisplayMode sets the initial display mode
//创建窗口时使用单缓冲区GLUT_SINGLE并使用RGB颜色模式
//一般双模式GLUT_DOUBLE是用于动画效果的场合
//这是两个默认的参数
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
//创建一个名为GLRect的窗口
glutCreateWindow("GLRect");
//callback
//glutDisplayFunc sets the display callback for the current window
//设置当前窗口的显示回调函数和窗口再整形回调函数
//这样当要绘制窗口,就会调用自定义RenderScene函数 比如添加一个图形
glutDisplayFunc(RenderScene);
//这样改变窗口,就会调用ChangeSize函数 比如放大或者缩小窗口
// glutReshapeFunc(void (*func)(int width, int height));
//The width and height parameters of the callback specify the new window size in pixels
//回调函数会指定对应窗口的大小,然后通过参数传递给width,height. 大概是这个意思吧。
//除了窗口大小改变会调用回调函数之外,当第一次创建窗口的时候,回调函数也会被调用。
glutReshapeFunc(ChangeSize);
//可以通过调式加深对这两个回调函数的理解。
//SetupRC并不是GLUT的框架,是自定义的函数, 其作用是进行OpenGL初始化
//OpenGL的初始化必须在渲染之前执行
SetupRC();
//启动主程序GLUT事件处理循环
//该函数让GLUT框架开始运行,所有设置的回调函数开始工作,
//直到用户终止程序为止
//也就是说,SetupRC是在渲染之前执行的。
glutMainLoop();
}</span></span>
个人理解。
修建区是绘制在视觉区上,视觉区绘制在窗口上。
类似qt图形项item绘制在场景scene, scene绘制在视觉区(view) 最后view在绘制在窗口上。
总结一下,一个OpenGL程序的基本结构主要包括以下几个部分。
(1)定义窗口:包括制定窗口的大小、位置、显示模式以及设置各种回调函数。
(2)初始化设置:清除各种缓冲区,并设置各种OpenGL状态,
例如设置背景色,打开光照,设置文理等等
(3)绘制场景:利用OpenGL函数绘制场景中的各种物体。
(4)变换:指定场景中需要显示的范围并指定由修建区到视区的变换。
(5)结束运行:清除命令缓冲区,执行OpenGL命令。
<span style="font-size:18px;">#include<windows.h>
#include<gl/glut.h>
#include<gl/gl.h>
#include<gl/glu.h>
#include<stdio.h>
/*
这个程序在上面那个基础上增加了
定时器:glutTimerFunc(unsigned int millis, void (*func)(int value), int value);
重绘标志:glutPosRedisplay();
定时器第一个参数是每隔millis毫秒便调用func函数,并且创一个value参数进去
因为一个定时器只被调用一次,所以需要多次调用定时器
完美结束
*/
//参数指定正方形的位置和大小
GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei rsize = 50; //int
//正方形运动变化的步长
GLfloat xstep = 1.0f;
GLfloat ystep = -10.0f;
//窗口的大小
GLfloat windowWidth;
GLfloat windowHeight;
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f,0.0f,0.0f);
glRectf(x1, y1, x1 + rsize, y1 + rsize);
//清空命令缓冲区并交换帧缓存
glutSwapBuffers();
}
void ChangeSize(GLsizei w, GLsizei h)
{
if (h == 0)
h = 1;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
printf("%d %d\n", w, h);
if (w <= h)
{
windowWidth = 250.0f;
windowHeight = 250.0f*h / w;
}
else
{
windowWidth = 250.0f*h / w;
windowHeight = 250.0f;
}
glOrtho(0.0f,windowWidth,0.0f,windowHeight,1.0f,-1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void TimerFunction(int value)
{
//处理到达窗口边界的正方形,使之反弹
if (x1 > windowWidth - rsize || x1 < 0) xstep = -xstep;
if (y1 > windowHeight - rsize || y1 < 0) ystep = -ystep;
if (x1 > windowWidth - rsize) x1 = windowWidth - rsize - 1;
if (y1 > windowHeight - rsize) y1 = windowHeight - rsize-1;
x1 += xstep;
y1 += ystep;
/*
glutPostRedisplay 标记当前窗口需要重新绘制。通过glutMainLoop下一次循环时,
窗口显示将被回调以重新显示窗口的正常面板。多次调用glutPostRedisplay,
在下一个显示回调只产生单一的重新显示回调
*/
glutPostRedisplay(); //标志重新绘制
glutTimerFunc(50,TimerFunction,1);
}
void SetupRC(void)
{
//设置窗口清除色为蓝色
glClearColor(0.0f,0.0f,1.0f,1.0f);
}
void main(void)
{
//使用双缓存技术
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutCreateWindow("Bounce");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
//定时器 每33毫秒触发一次
glutTimerFunc(50,TimerFunction,1);
SetupRC();
glutMainLoop();
}</span>
版权声明:本文为qq_33850438原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。