OpenGL三维几何变换 & 材质光照

显示效果:

源码:

#define NDEBUG
#ifndef GLUT_DISABLE_ATEXIT_HACK
#define GLUT_DISABLE_ATEXIT_HACK
#endif
#include <windows.h>
#include <gl/glut.h>
#include <math.h>
#include <stdio.h>
#include <vector>using namespace std;const int windowWidge=600, windowHeight=600;static GLfloat angle = 0.0f;
static GLfloat moonAngle=0.0f;
static GLfloat sunAngle=0.0f;//初始化绘制
void init(){glClearColor(0.0,0.0,0.0,0);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  //清理颜色和深度缓存// 创建透视效果视图glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(80.0, 1.0f, 1.0f, 50.0f);//定义视点位置:glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0.0, 30.0, 10.0, 0.0, 0.0, 0.0, 0.0, -1, 3.0);// 定义太阳光源,它是一种白色的光源{GLfloat sun_light_position[] = {0.0f, 0.0f, 0.0f, 1.0f}; //光源的位置在世界坐标系圆心,齐次坐标形式GLfloat sun_light_ambient[]   = {0.1f, 0.1f, 0.1f, 1.0f}; //RGBA模式的环境光GLfloat sun_light_diffuse[]   = {1.0f, 234.0/255, 106.0/255, 1.0f}; //RGBA模式的漫反射光,全白光GLfloat sun_light_specular[] = {1.0f, 234.0/255, 106.0/255, 1.0f};  //RGBA模式下的镜面光 ,全白光glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position);glLightfv(GL_LIGHT0, GL_AMBIENT,   sun_light_ambient);glLightfv(GL_LIGHT0, GL_DIFFUSE,   sun_light_diffuse);glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular);//开启灯光glEnable(GL_LIGHT0);glEnable(GL_LIGHTING);glEnable(GL_DEPTH_TEST);}return ;
}void display(){glClearColor(0.0,0.0,0.0,0);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 定义太阳的材质并绘制太阳{GLfloat sun_mat_ambient[]   = {1.0f, 234.0/255, 106.0/255, 1.0f};  //定义材质的环境光颜色GLfloat sun_mat_diffuse[]   = {0.0f, 0.0f, 0.0f, 1.0f};  //定义材质的漫反射光颜色GLfloat sun_mat_specular[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的镜面反射光颜色GLfloat sun_mat_emission[] = {1.0f, 234.0/255, 106.0/255, 1.0f};   //定义材质的辐射光颜色GLfloat sun_mat_shininess   = 0.0f;glMaterialfv(GL_FRONT, GL_AMBIENT,    sun_mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE,    sun_mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,   sun_mat_specular);glMaterialfv(GL_FRONT, GL_EMISSION,   sun_mat_emission);glMaterialf (GL_FRONT, GL_SHININESS, sun_mat_shininess);glPushMatrix ();glRotated (sunAngle,0.0f, 0.0f, 1.0f);glutSolidSphere(4.0, 40, 32);glPopMatrix ();}// 定义地球的材质并绘制地球{GLfloat earth_mat_ambient[]   = {0.0f, 0.0f, 1.0f, 1.0f};  //定义材质的环境光颜色GLfloat earth_mat_diffuse[]   = {0.0f, 0.0f, 1.0f, 1.0f};  //定义材质的漫反射光颜色GLfloat earth_mat_specular[] = {1.0f, 234.0/255, 106.0/255, 1.0f};   //定义材质的镜面反射光颜色GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的辐射光颜色GLfloat earth_mat_shininess   = 32.0f;glMaterialfv(GL_FRONT, GL_AMBIENT,    earth_mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE,    earth_mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,   earth_mat_specular);glMaterialfv(GL_FRONT, GL_EMISSION,   earth_mat_emission);glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess);glPushMatrix ();glRotatef(angle, 0.0f, 0.0f, 1.0f);glTranslatef(10.0f, 0.0f, 0.0f);glutSolidSphere(2.0, 40, 32);     //半径为2, 40条纬线, 32条经线glPopMatrix ();}
//  定义月球材质并绘制月球{GLfloat moon_mat_ambient[]   = {225.0/255, 225.0/255, 220.0/255, 1.0f};  //定义材质的环境光颜色GLfloat moon_mat_diffuse[]   = {225.0/255, 225.0/255, 220.0/255, 1.0f};  //定义材质的漫反射光颜色GLfloat moon_mat_specular[] = {1.0f, 234.0/255, 106.0/255, 1.0f};   //定义材质的镜面反射光颜色GLfloat moon_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};   //定义材质的辐射光颜色GLfloat moon_mat_shininess   = 128.0f;glMaterialfv(GL_FRONT, GL_AMBIENT,    moon_mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE,    moon_mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR,   moon_mat_specular);glMaterialfv(GL_FRONT, GL_EMISSION,   moon_mat_emission);glMaterialf (GL_FRONT, GL_SHININESS, moon_mat_shininess);//绕地球旋转:glPushMatrix ();glRotatef(angle, 0.0f, 0.0f, 1.0f);glTranslatef(10.0f, 0.0f, 0.0f);glRotatef(-angle, 0.0f, 0.0f, 1.0f);glRotatef (moonAngle,0.0f, 0.0f, 1.0f);glTranslatef (4.0f, 0.0f, 0.0f);glutSolidSphere(1.0, 40, 32);        //半径为2, 40条纬线, 32条经线glPopMatrix ();}glutSwapBuffers();return ;
}void myIdle(void){angle += 0.5f;moonAngle +=2.0f;sunAngle +=1.0f;if( angle >= 360.0f ){angle = 0.0f;}if(moonAngle >=360.0f){moonAngle=0.0f;}glutPostRedisplay();Sleep(10);return;
}int main(int argc, char** argv){glutInit(&argc, argv);//初始化glutglutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);//设置显示模式为单缓冲,RGB模式glutInitWindowPosition(0,0);//设置窗口位置glutInitWindowSize(windowWidge,windowHeight);//设置窗口大小glutCreateWindow("太阳系");//设置窗口标题init();glutDisplayFunc(display);glutIdleFunc(myIdle);glutMainLoop();return 0;
}

源码分析:

视点透视:

// 创建透视效果视图
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(80.0, 1.0f, 1.0f, 50.0f);
  • 先搞明白glMatrixMode()

    glMatrixMode是用来指定哪一个矩阵是当前矩阵,而它的参数代表要操作的目标

    GL_PROJECTION是对投影矩阵操作
    GL_MODELVIEW是对模型视景矩阵操作
    GL_TEXTURE是对纹理矩阵进行随后的操作

  • 之前讲到openGL有两种投影: 正射投影(垂直投影)和透视投影

    前者不用缩放, 后者使用缩放

  • 通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。
    所以后头会跟上一个:

    glLoadIdentity();

  • gluPerspective(80.0, 1.0f, 1.0f, 50.0f);

    设置当前可视空间为透视投影空间, 并设置透视投影的参数

    之前用的都是glOrtho
    此为设置当前可视空间为正投影空间

    void gluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
    

    几个参数与图中的视角相对应:

    1. 视线张角

      当张角变小时, 相当于显微镜, 将更小范围内的东西放大到固定的屏幕, 反之缩小

      当=180时, 物体变的无限小, 不可见, 当=0时, 视线关闭, 不可见

    2. 宽高比w/h

    3. zNear表示近裁剪面到眼睛的距离,zFar表示远裁剪面到眼睛的距离

      这两个都不能设置为负值

定义视点:

//定义视点:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 30.0, 10.0, 0.0, 0.0, 0.0, 0.0, -1, 3.0);
  • 前两个和之前一样

  •   void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);
    

    定义视点, 分为三组坐标

    1. 第一组定义了视点在世界坐标系中的坐标
    2. 第二组定义了视点看向的位置
    3. 第三组定义了视点向上方向的在世界坐标系中的方向向量(头顶位置)

光照:

具体的光照详解可以参考这一篇:

https://blog.csdn.net/chuifuhuo6864/article/details/100886020

三维变换:

三维变换具体可以参考这篇博客:

https://www.cnblogs.com/tjulym/p/5049313.html

glPushMatrix ();
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glTranslatef(10.0f, 0.0f, 0.0f);
glutSolidSphere(2.0, 40, 32);       //半径为2, 40条纬线, 32条经线
glPopMatrix ();
  • 矩阵入栈, 而后对此矩阵进行操作

以下的操作都可以看做是对当前坐标轴的变换, 初始坐标轴与世界坐标轴重合

  • 旋转:

    glRotatef(GLfloat angle,GLfloat x,GLfloat y,GLfloat z)
    
    1. angle:
      旋转的角度

    2. 后头一组坐标为旋转轴的方向向量

      将以此向量为上进行逆时针旋转

  • 平移:

    void glTranslatef(GLfloat x,GLfloat y,GLfloat z);
    

    以当前坐标轴为基准, 将当前坐标轴平移到(x,y,z)的位置

  • 画一个刚体球:

    void glutSolidSphere(GLdouble r,GLint ,GLint);
    
    • r
      球的半径
    • 后头两个参数为球的纬线&经线的条数
      实际画出的是一个多面体, 所以纬线与经线越多, 就越接近真实球体
  • 弹出当前操作的矩阵

    矩阵堆栈有容量上限, 及时弹出防止爆栈

画面刷新:

glutIdleFunc(myIdle);
void myIdle(void){angle += 0.5f;moonAngle +=2.0f;sunAngle +=1.0f;if( angle >= 360.0f ){angle = 0.0f;}if(moonAngle >=360.0f){moonAngle=0.0f;}sleep(10);glutPostRedisplay();return;
}
  • glutIdleFunc(void (*callback) ())

    闲时调用函数, 当openGL空闲时会调用传给他的函数func

  • myIdle()

    返回值与参数均为void

    在空闲时被调用, 更新当前角度啥的

    而后一个sleep() 防止刷新率过高

  • glutPostRedisplay()

    相当于直接调用display()来刷新窗口, 但后者更加智能一点

计算机图形学の三维几何变换材质光照(OpenGL)相关推荐

  1. 计算机图形学规则形体,计算机图形学 三维形体的表示ppt课件.ppt

    <计算机图形学 三维形体的表示ppt课件.ppt>由会员分享,提供在线免费全文阅读可下载,此文档格式为ppt,更多相关<计算机图形学 三维形体的表示ppt课件.ppt>文档请在 ...

  2. 计算机图形基础实验图形变换,北方工业大学 计算机图形学实验 几何变换

    北方工业大学 计算机图形学实验 几何变换 四.用OpenGL函数库实现几何图元旋转特效 在Nehe教程Lesson04基础上,修改程序,在屏幕上画两个三角形.两个四边形,并完成相应动画效果,三角形A绕 ...

  3. 游戏开发计算机图形学杂项知识系列:OpenGL红宝书中第一个渲染程序Triangles常见问题归总

    游戏开发计算机图形学杂项知识系列:OpenGL红宝书中第一个渲染程序Triangles常见问题归总 声明:未经作者允许,严禁商用,转载请标明出处和来源,谢谢 转载自:https://www.cnblo ...

  4. 计算机图形学——三维图形几何变换和投影转换(VC)

    实验目的 掌握4*4矩阵乘法运算的编程实现: 掌握平移.比例.旋转三种基本三维几何变换矩阵生成: 掌握正交投影图的生成和绘制方法. 实验要求 三维坐标系的原点位于屏幕中心,X轴水平向右,Y轴垂直向上, ...

  5. 计算机图形学三维建模及灯光作业(派大星)

    计算机图形学设计人物派大星,以下是参考代码. 需要函数库的私信我. 运行环境:VC 6.0 引擎库:OpenGL 完整代码: #include <GL/glut.h> #include & ...

  6. 计算机图形学中几何变换的定义,计算机图形学-第5章-几何变换课件

    <计算机图形学-第5章-几何变换课件>由会员分享,可在线阅读,更多相关<计算机图形学-第5章-几何变换课件(70页珍藏版)>请在人人文库网上搜索. 1.计算机图形学-第5章-几 ...

  7. 计算机图形学三维变换论文,计算机图形学 第5章 三维图形生成和变换技术

    计算机图形学 第5章 三维图形生成和变换技术 (63页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 第五章 目录第五章 三维图形生成和变 ...

  8. 计算机图形学三维投影程序,三维计算机图形学

    <三维计算机图形学>是科学出版社出版.本书共分17章,内容包括IDE环境与编程基础.基本语法与数据类型.运算操作.流程控制.面向对象程序设计.用户界面编程.文件系统管理.图形图像多媒体编程 ...

  9. 计算机图形学基础:实验5 OpenGL二维几何变换

    1.实验目的: 理解并掌握OpenGL二维平移.旋转.缩放变换的方法. 2.实验内容: 阅读实验原理,掌握OpenGL程序平移.旋转.缩放变换的方法. 根据示范代码,完成实验作业. 3.实验原理: ( ...

最新文章

  1. android实现长截屏,Android实现全屏截图或长截屏功能
  2. NFS共享服务挂载时出现“access denied by server while mounting”的解决方法
  3. linux如何时间更新最新版本,桌面应用|Linux有问必答:如何更新过期版本的Ubuntu...
  4. java中用byte[]数组实现的队列和用Byte[]实现的队列实际占用空间对比
  5. T-SQL 之 多表联合更新
  6. 前端之路(一)之W3C是什么?
  7. Docverter – 文本文件轻松转换为 PDF,Docx 和 ePub 文件
  8. python多线程框架_基于python和bash的多线程任务框架 不要让cpu闲着了
  9. HTML+CSS+JS实现 ❤️酷炫的canvas全屏背景动画特效❤️
  10. 神经网络优化算法总结【SGD】---【Adam】
  11. idea如何安装scala插件
  12. flowable 中文文档_取出word文档文字内容生成加了目录、标号和页码的PDF文件
  13. 浮点型变量的误差问题
  14. 顶级大厂如何做好暗黑模式设计?来看 Ant Design 的规范文档
  15. 如何为水晶报表rpt文件添加数据连接
  16. 计算机在语文教学中,计算机技术在语文教学中的运用
  17. C语言实现三子棋(嘎嘎权威)
  18. 再论EOS的CPU租赁利率,无风险套利?
  19. js根据经纬度计算多边形面积
  20. 学习C语言的相关网站(C学习资料)

热门文章

  1. C# 将object类型转换成List
  2. Java后端使用socketio,实现小程序答题pk功能
  3. 浅谈 MVC与三层架构
  4. cxp文件查看 欧姆龙_cxp格式怎么打开
  5. 隧道调频广播覆盖方案
  6. android l 新功能,Android L怎么样 安卓L新特性汇总
  7. 使用ownCloud搭建私人存储云(以Ubuntu12.04为例)
  8. 信用卡的使用之一——宽限期
  9. 实时控制软件第一次作业--CNC软件系统分析
  10. 实践教程|GPU 利用率低常见原因分析及优化