学习资料有:
1.Microsoft官方的opengl-glut文章,最全面,全英文,可作为字典查阅使用
2.博主xie_zi的opengl-glut专栏,通俗的文章
3.知乎的opengl-glut文章
3.opengl-glut文档
4.open-glfw/glad的文章
本文较长(其实主要是贴的代码比较长),可每天学一部分,结合专栏,官方网址学习,个人仅仅记个笔记,讲的并不深入,真正的理解还是需要多方面查资料一步步啃啊,一起努力把
1.buffer n./v. 缓冲,保护
2.flush v.冲洗,脸红
3.vertex/vertice n.顶点
4.render v.绘制
5.display v./n.陈列,展示
6。func/function n.函数
7.syntax n.句法,语法
8.parameter n.界限,范围,参数,变量
9.modify v.修改
10.projection n.估算,预测;投射,投影
3.15
用vs安装OpenGL的glut的文章
头文件
#include
opengl四个库
OpenGL的基本库(GL): 库文件:opengl32.lib,头文件:gl.h
OpenGL实用库(GLU): 库文件:glu32.lib,头文件:glu.h
OpenGL Programming Guide辅助库(glaux): 库文件:glaux.lib,头文件:glaux.h
OpenGL的工具库(glut): 库文件:glut32.lib,头文件:glut.h
**
**
OpenGL的函数在格式上很有特点,它以gl为前缀并且函数名的最后一个字母指出所用的数据类型,如:glColor3f(),字母f指明要使用浮点数。字母前的数字指明参数个数或指明二维还是三维,如: glVertex2f()是要设置二维的点。
glVertex2i()是设置int类型的二维的点
main函数几个组成部分
int main()
{
glutInit(&argc, argv); //初始化
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // 显示模式
glutInitWindowPosition(50, 100); // 窗口位置
glutInitWindowSize(400, 400); //窗口大小
glutCreateWindow("An Example OpenGL Program"); //开始创建
init();//接下来讲
glutDisplayFunc(f); // 进入绘画,f为用于绘画的函数名
glutMainLoop(); //保持窗口不消失
return 0;
}
(1)还有个init函数
glMatrixMode函数指定哪个矩阵是当前矩阵
gluOrtho2D定义二维正交投影矩阵
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); // Set display-window color to white.
glMatrixMode(GL_PROJECTION); // Set projection parameters.
gluOrtho2D(0.0, 200.0, 0.0, 150.0);//gluOrtho2D 函数定义二维正交投影矩阵。
}
(2)main其中的函数
Void glutInitDisplayMode(unsighed int mode)
参数:
Mode――可以指定下列显示模式
Mode参数是一个GLUT库里预定义的可能的布尔组合。你使用mode去指定颜色模式,数量和缓冲区类型。
指定颜色模式的预定义常量有:
1:GLUT_RGBA或者GLUT_RGB。指定一个RGBA窗口,这是一个默认的颜色模式。
2:GLUT_INDEX。指定颜色索引模式。
这个显示模式还允许你选择单缓冲区或双缓冲区窗口。
1:GLUT_SINGLE.单缓冲区窗口。
2:GLUT_BUFFER.双缓冲区窗口,这是产生流畅动画必须选的。
还可以指定更多,如果你想指定一组特殊的缓冲的话,用下面的变量:
1:GLUT_ACCUM.累积缓冲区。
2:GLUT_STENCIL.模板缓冲区。
3:GLUT_DEPTH.深度缓冲区。
假定你想要一个有单缓冲区,深度缓冲区的RGB窗口
你用“或“(|)操作符来建立你想要的显示模式。
…………….
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE|GLUT|DEPTH);
…………….
(1)颜色缓冲区、深度缓冲区、模板缓冲区和累积缓冲区
(2)opengl深度缓冲,深度测试
相关博客:
opengl函数详解
用到的函数有:
glClear//清除颜色缓冲区
glColor3f//设置颜色
glBegin//开始绘制
glEnd//结束绘制
一个例子:
void f (void)
{
glClear (GL_COLOR_BUFFER_BIT); // Clear display window.清除颜色缓冲区
glColor3f (0.0, 0.0, 1.0); // Set line segment color to red.设置颜色
glBegin (GL_LINES);
glVertex2i (180, 15); // Specify line-segment geometry.
glVertex2i (10, 145);
glEnd ( );
glFlush ( ); // Process all OpenGL routines as quickly as possible.
}
无论 OpenGL 绘制的 3D 画面多么复杂和优美,实质上它们都是由许许多多的点、线、
多边形等基本几何对象构成的,而这也是 OpenGL 可以提供的最基本的绘制功能。如果你
有足够的时间和耐心,可以使用 OpenGL 的这些基本对象去构造绚丽多彩的 3D 画面。因
此,学习 OpenGL 的简单 3D 建模方法是步入 OpenGL 程序设计领域的第一步,也是不可
或缺的一步。
说明:
像是颜色,大小(点,线)这类属性都在glBegin()之前规定,在glBegin()内规定无效,而在glBegin()内规定的是绘制操作
(因为我试过一部分qwq,可以试试看,感觉是这样)
OpenGL采用的是状态机的方式,用户设定一种状态,程序照此运行。如:
(1)glBegin(GL_LINES)设定画线状态。main()函数中的几个glut前缀函数是OpenGL提供的工具库,我们关注的是display()函数,它是我们真正绘图的地方。
(2)与颜色有关的函数:
(1)函数glColor3f()以RGB方式设置颜色,
格式为:glColor3f(red, green, blue),每种颜色值在(0.0, 1.0)之间。
为了能显示更多的颜色,最好把系统设置成16位真彩色模式。
函数glVertex2i(x, y)设置整型二维顶点。
(2) glColor4ub 函数
函数原型: void WINAPI glColor4ub(
GLubyte red,
GLubyte green,
GLubyte blue,
GLubyte alpha
);
参数:
红
当前颜色的新红色值。
绿
当前颜色的新绿色值。
蓝
当前颜色的新蓝色值。
alpha
当前颜色的新 alpha 值。
(3)glClearColor(1.0, 1.0, 1.0, 0.0);
Set display-window color to white.
把新开的窗口背景设置为白色
(3)OpenGL 虽然分别提供了二维和三维顶点的绘制方法,但二维图形不过是三维图形的
特殊情况(z 分量为 0),在三维顶点绘制指令中,如果用户设定二维坐标(x, y),OpenGL 就
会自动令 z=0。因此,这里将三维基本图元和二维基本图元放在一起介绍。
OpenGL 提供的描述点、线、多边形的绘制机制必须通过 glBegin()和 glEnd()函数配对
来完成,下面对这两个函数作简要说明。
void glBegin(GLenum mode)
功能:描述一个几何图元顶点序列的开始。
参数说明:
mode 指出图元的类型。类型可以是下面中的任一个值。
GL_POINTS 画点
GL_LINES 画线,每两个顶点(Vertex)为一组
GL_LINE_STRIP 画线,把若干个顶点顺次连成折线
GL_LINE_LOOP 画线,把若干个顶点顺次连成封闭折线
GL_TRIANGLES 画三角形,每三个顶点为一组
GL_QUADS 画四边形,每四个顶点为一组
GL_POLYGON 画多边形
还有GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS_STRIP 等等。
//下面这两个看不懂不要紧,可以不看,下方有图,有助于理解
GL_TRIANGLE_STRIP strip:带状,条状的意思
在绘制朝一个方向延展的图形时选择它。
绘制一组相互连接的三角形。
为前两个顶点之后的每个顶点定义一个三角形。
对于奇数n,顶点n、n + 1和n + 2定义三角形n。
对于偶数n,顶点n + 1、n和n + 2定义三角形n。
绘制n - 2个三角形。
GL_TRIANGLE_FAN fan:扇形
在绘制扇形、圆形时选择它。
GL_QUAD_STRIP 绘制一组连通的四边形。在第一对顶点之后,
每对顶点定义一个四边形。
顶点2n - 1,2n, 2n + 2和2n + 1定义了四边形n。
绘制了n /2 - 1个四边形。
注意,从条形数据构造四边形所使用的顶点顺序
与独立数据所使用的顺序不同。
void glEnd (void)
功能:标记顶点表的结束。
在 OpenGL 中,所有的图元绘制都是在这对函数中完成的。
参考文章:
1.OpenGL 理解GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN等绘制三角形序列的三种方式
2.【OpenGL】十五、OpenGL 绘制三角形 ( 绘制 GL_TRIANGLE_FAN 三角形扇 )
3.OpenGL 解析glBegin()
看到图三,那我们是不是可以试着用它来画圆呢?
接下来我们说一说基本图元:
用到的函数有
glVertex//画点
glPointSize//规定点的大小
glVertex{2,3,4}{sifd}(V)(TYPE coords);
参数说明:
coords:用一个数组或用齐次坐标(x, y, z, w)赋顶点坐标
例如:
glVertex2f(1.5,2.6);
glVertex2i(1,2);
glVertex3d(2.12,3.48,6.57);
glVertex3f(50.0,50.0,0.0);
glVertex4f(1.3,2.0,-4.2,1.0);
glVertex3sv(const Glshort *v);
程序执行到 glBegin()和 glEnd()时,就开始绘图操作。请看下面的例子:
glBegin(GL_POINTS);
glVertex3f(0.0,0.0,0.0)
glVertex3f(50.0,50.0,50.0)
glEND();
glBegin()的参数 GL_POINTS 告诉 OpenGL,下面的顶点应被解释并绘制为点,它们将
转换为两个具体的点,并被绘制出来,其颜色为默认值指明的颜色。
2) 点的大小
OpenGL 提供了可以控制点的大小的函数。点大小的默认值是一个像素。可以用函数
修改这个值,以设定点的大小:
void glPointsize(GLfloat size) //具体代码看博客glPointsize()
首先解释一下:走样,什么是走样?汉语字典给的定义是:变样,失去原有的样子。
反走样,也就是不让它走样;
是否启动反走样,对绘制点操作有一定影响。如果没有启动反走样,所绘制的点是一
个正方形块,浮点数四舍五入为整数宽度;如果启动反走样,则画一个圆形像素集,边界
像素用低的颜色强度绘制,用浮点数不进行四舍五入,从而使所画的点看上去很光滑。
相关的博文:OpenGL基础(二):线
用到的函数有:
glVertex//画点
glLineStipple//启动点画线模式,stipple v.点画,点刻,点彩n.点画,点刻法
glEnable(GL_LINE_STIPPLE)。//开启点画线
glDisable(GL_LINE_STIPPLE)。//关闭点画线用
glLineWidth//同点的大小道理一样
(1) 用线型属性可以绘制虚线或点线,在 OpenGL 中统称为点画线。为了使用点画线,必
须用以下指令先启动点画线模式。
void glLineStipple (GLint factor,GLushort pattern);
此命令有以下参数:
factor 是一个 1~255 的值,它表示 pattern 参数中所规定的像素的重复次数,即 pattern
参数中每一位能影响的像素数。
pattern 是画线操作时的一个样板。它是二进制的一个 0 和 1 的序列,在这个序列中 0
表示不画点,1 表示画点。
如果启动点画线操作,线上的点由 pattern 决定是否绘制,即从 pattern 的最低位开始,
逐个绘制线段上的点,如果式样用完后,线段还没有画完,则需重新装入样板。以下例子
说明此函数的应用。
glLineStipple (1,0x3F07)
此命令执行时,0x3F07 转化为二进制为 0011 1111 0000 0111。在画线操作时,首先绘
制开始的 3 个像素点,接下来 5 个点不绘制,6 个点绘制,2 个点不绘制。如果点画线的样
板用完,则将从头开始。
上例中,若 factor=2,那么 pattern 实际上就成为:00001111 11111111 00000000
00111111,结果为,6 个像素点画,10 个像素点不画,12 个像素点画,4 个像素点不画。
启动点画线用 glEnable(GL_LINE_STIPPLE)。
关闭点画线用 glDisable(GL_LINE_STIPPLE)
(2)线宽:
glLineWidth(GLfloat width);
代码如下:
#include
void init()
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION); // Set projection parameters.
gluOrtho2D(0.0, 200.0, 0.0, 150.0);
}
void f()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLineWidth(10);//线宽
glEnable(GL_LINE_STIPPLE);
glLineStipple(3, 0xAAAA);//开启点画线
glColor3f(1.0, 0.0, 1.0);//设置颜色
glBegin(GL_LINES);
glVertex2i(20, 20);
glVertex2i(50, 50);
glEnd();
glDisable(GL_LINE_STIPPLE);
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINES);
glVertex2i(70, 30);
glVertex2i(100, 50);
glEnd();
glFlush();
}
int main(int argc,char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(400, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("3.25");
init();
glutDisplayFunc(f);
glutMainLoop();
return 0;
}
相关博客:
OpenGL基础(三):三角形
OpenGL基础(四):四边形
用到的函数:
glPolygonStipple()//图案填充
glEnable(GL_POLYGON_STIPPLE)//启动多边形点画式样。
glDisable(GL_POLYGON_STIPPLE)//关闭多边形点画式样。
画线
用 GL_LINES
#include // (or others, depending on the system in use)
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); // Set display-window color to white.
glMatrixMode(GL_PROJECTION); // Set projection parameters.
gluOrtho2D(0.0, 200.0, 0.0, 150.0);//gluOrtho2D 函数定义二维正交投影矩阵。
}
void lineSegment(void)
{
glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
glColor3f(0.0, 0.0, 1.0); // Set line segment color to red.
glBegin(GL_LINES);
glVertex2i(180, 15); // Specify line-segment geometry.
glVertex2i(10, 145);
glEnd();
glFlush(); // Process all OpenGL routines as quickly as possible.
}
void main(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // Set display mode.
glutInitWindowPosition(50, 100); // Set top-left display-window position.
glutInitWindowSize(400, 400); // Set display-window width and height.
glutCreateWindow("An Example OpenGL Program"); // Create display window.
init(); // Execute initialization procedure.
glutDisplayFunc(lineSegment); // Send graphics to display window.
glutMainLoop(); // Display everything and wait.
}
画圆
头文件
用GL_POLYGON
3.16
为了窗口改变时,保证初始化窗口不是正方形的时候渲染也不会变形出错。
void glutReshapeFunc(void(*func)(int width,int height));
glutReshapeFunc(g(w,h));//main函数中调用
void g(int w,int h)
{// 防止除数即高度为0
// (你可以设置窗口宽度为0).
if(h == 0)
h = 1;
float ratio = 1.0* w /h;
// 单位化投影矩阵。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// 设置视口大小为增个窗口大小
glViewport(0, 0, w, h);
// 设置正确的投影矩阵
gluPerspective(45,ratio,1,1000);
//下面是设置模型视图矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0,0.0f , 1.0f , 0.0f );
}
没学习线代,我也看着挺懵逼,(等我学会了再来补充吧)
2023.3.17 星期五
博主的文章
main()函数:
增加些额外的设置。首先告诉GLUT我们想要一个双缓冲区。双缓冲区通过在后一个缓冲区里绘画,并不停交换前后缓冲区(可见缓冲区),来产生平滑的动画。使用双缓冲区可以预防闪烁。
glutInitDisplayMode(GL_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
接着我们要做的是告诉GLUT,当应用程序空闲的时候渲染函数应该被调用。这导致GLUT一直调用渲染函数而产生动画。GLUT提供了一个函数:glutIdleFunc.这个函数使另一个函数在程序空闲的时候就会被调用。
void glutIdleFunc(void(*func)(void));
参数:
func:在程序空闲的时候就会被调用的函数的函数名。
按照我们的想法,当程序空闲时应该调用的函数是我们先前定义的渲染函数: renderScene。由于OpenGL默认没有开启深度测试,我们还要开启它,这样我们才能知道哪个物体在前面,哪个物体在后面。深度测试的开启在main()函数里,下面看看现在的main函数。
void main(int argc, char **argv) {
glutInit(&argc, argv);
// 在这里设置双缓冲区。
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("3D Tech- GLUT Tutorial");
glutDisplayFunc(renderScene);//画图
// 这里让程序空闲时调用renderScene,
glutIdleFunc(renderScene);//动画
glutReshapeFunc(changeSize);//防止窗口改变
//开启深度测试。
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}
float angle=0.0;
void renderScene(void) {
//注意我们这里清除了深度缓冲区。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//1
//保存当前模型视图矩阵。
glPushMatrix(); //2
glRotatef(angle,0.0,1.0,0.0);//3
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0.0);
glVertex3f (0.5,0.0,0.0);
glVertex3f (0.0,0.5,0.0);
glEnd();
// 弹出堆栈
glPopMatrix();//4
// 交换缓冲区
glutSwapBuffers();//5
// 让angle自动增加。
angle++; //6
//新增了6句话
}
对 5 的解释
用法
void glutSwapBuffers(void);
描述
对用于当前窗口的图层执行缓冲区交换。
具体来说, glutSwapBuffers 将当前窗口
使用的层的后台缓冲区的内容提升为 前端缓冲区的内容。
然后,后台缓冲区的内容 变得未定义。
更新通常在垂直期间进行 监视器的回溯,
而不是在调用 glutSwapBuffers 后立即回溯。
隐式 glFlush 由 glutSwapBuffers 在返回之前完成。
后续的 OpenGL 命令可以在调用 glutSwapBuffer 后立即发出,
但在缓冲区交换之前不会执行 已完成。
如果使用的层不是双缓冲的,则 glutSwapBuffers 不起作用。
//有点懵逼是吧,是的,我也是qwq,别骂我,我就是为了记个笔记,为了以后理解了再来补充的qwq
2023.3.18 星期六
学习时参考
博主的文章qwq
可以通过键盘让图形变色,是的,它很炫酷
在这里给出了完整代码
#include
#include
#include
const int n = 100;
const GLfloat R = 0.3f;
const GLfloat r = 0.6f;
const GLfloat Pi = 3.1415926;
float red = 1.0, blue = 1.0, green = 1.0;
float angle = 0.0;
void processSpecialKeys(int key, int x, int y) {
switch (key) {
case GLUT_KEY_F1:
red = 1.0;
green = 0.0;
blue = 0.0; break;//红色
case GLUT_KEY_F2:
red = 0.0;
green = 1.0;
blue = 0.0; break;//绿色
case GLUT_KEY_F3:
red = 0.0;
green = 0.0;
blue = 1.0; break;//深蓝色
case GLUT_KEY_F4:
red = 1.0;
green = 0.6;
blue = 0.9; break;//粉色
case GLUT_KEY_F5:
red = 0.0;
green = 0.6;
blue = 0.9; break;//蓝色
case GLUT_KEY_F6:
red = 0.0;
green = 1.0;
blue = 0.9; break;//浅绿色
case GLUT_KEY_F7:
red = 0.0;
green = 0.8;
blue = 0.9; break;//浅绿色
}
}
void f(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(angle, 0.0, 1.0, 0.0);
// glColor3f设置绘制三角形的颜色。
glColor3f(red, green, blue);
glBegin(GL_POLYGON);
for (int i = 0; i < n; i++)
{
glVertex2f(R*cos(2 * Pi / n * i), R*sin(2 * Pi / n * i));
}
glEnd();
glPopMatrix();
angle++;
glutSwapBuffers();
}
void changesize(int w, int h)
{
{// 防止除数即高度为0
// (你可以设置窗口宽度为0).
if (h == 0)
h = 1;
float ratio = 1.0* w / h;
// 单位化投影矩阵。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// 设置视口大小为增个窗口大小
glViewport(0, 0, w, h);
// 设置正确的投影矩阵
gluPerspective(45, ratio, 1, 1000);
//下面是设置模型视图矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, -1.0, 0.0f, 1.0f, 0.0f);
}
}
void main(int argc, char** argv) {
glutInit(&argc, argv);
// 在这里设置双缓冲区。
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(320, 320);
glutCreateWindow("3D Tech- GLUT Tutorial");
glutDisplayFunc(f);
glutSpecialFunc(processSpecialKeys);
// 这里让程序空闲时调用renderScene,
glutIdleFunc(f);
/*glutReshapeFunc(changeSize);*/
//开启深度测试。
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}
2023.3.19 星期日
文章场景漫游
这篇文章绘制了雪人,让我们以照相的视角进行移动
代码如下,可以贴来试试
#include
#include
#include
static float angle = 0.0, ratio;
static float x = 0.0f, y = 1.75f, z = 5.0f;
static float lx = 0.0f, ly = 0.0f, lz = -1.0f;
static GLint snowman_display_list;
void changeSize(int w, int h)
{
// 防止被0除.
if (h == 0)
h = 1;
ratio = 1.0f * w / h;
// Reset the coordinate system before modifying修改前请重置坐标系统
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//设置视口为整个窗口大小
glViewport(0, 0, w, h);
//设置可视空间
gluPerspective(45, ratio, 1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(x, y, z,
x + lx, y + ly, z + lz,
0.0f, 1.0f, 0.0f);
}
//下面我们定义显示列表,绘制雪人,初始化场景,渲染场景。
void drawSnowMan() {
glColor3f(1.0f, 1.0f, 1.0f);
//画身体
glTranslatef(0.0f, 0.75f, 0.0f);
glutSolidSphere(0.75f, 20, 20);
// 画头
glTranslatef(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.25f, 20, 20);
// 画眼睛
glPushMatrix();
glColor3f(0.0f, 0.0f, 0.0f);
glTranslatef(0.05f, 0.10f, 0.18f);
glutSolidSphere(0.05f, 10, 10);
glTranslatef(-0.1f, 0.0f, 0.0f);
glutSolidSphere(0.05f, 10, 10);
glPopMatrix();
// 画鼻子
glColor3f(1.0f, 0.5f, 0.5f);
glRotatef(0.0f, 1.0f, 0.0f, 0.0f);
glutSolidCone(0.08f, 0.5f, 10, 2);
}
GLuint createDL() {
GLuint snowManDL;
//生成一个显示列表号
snowManDL = glGenLists(1);
// 开始显示列表
glNewList(snowManDL, GL_COMPILE);
// call the function that contains
// the rendering commands
drawSnowMan();
// endList
glEndList();
return(snowManDL);
}
void initScene() {
glEnable(GL_DEPTH_TEST);
snowman_display_list = createDL();
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//画了一个地面
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, 100.0f);
glVertex3f(100.0f, 0.0f, -100.0f);
glEnd();
//画了36个雪人
for (int i = -3; i < 3; i++)
for (int j = -3; j < 3; j++) {
glPushMatrix();
glTranslatef(i*10.0, 0, j * 10.0);
glCallList(snowman_display_list);;
glPopMatrix();
}
glutSwapBuffers();
}
void orientMe(float ang) {
lx = sin(ang);
lz = -cos(ang);
glLoadIdentity();
gluLookAt(x, y, z,
x + lx, y + ly, z + lz,
0.0f, 1.0f, 0.0f);
}
void moveMeFlat(int direction) {
x = x + direction * (lx)*0.1;
z = z + direction * (lz)*0.1;
glLoadIdentity();
gluLookAt(x, y, z,
x + lx, y + ly, z + lz,
0.0f, 1.0f, 0.0f);
}
//这里我们建立函数,处理特殊键按下消息。使用左右方向键旋转照相机,也就是改变视线。上下方向键使照相机沿视线前后移动。
void inputKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT:
angle -= 0.01f;
orientMe(angle); break;
case GLUT_KEY_RIGHT:
angle += 0.01f;
orientMe(angle); break;
case GLUT_KEY_UP:
moveMeFlat(1); break;
case GLUT_KEY_DOWN:
moveMeFlat(-1); break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(640, 360);
glutCreateWindow("SnowMen from 3D-Tech");
initScene();
glutSpecialFunc(inputKey);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glutMainLoop();
return(0);
}
先告一段落,因为还没学习线代,矩阵部分有点吃力,以后会继续补充