OpenGL中的投影使用

OpenGL中的投影使用

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

OpenGL中的投影使用


         在OpenGL中,投影矩阵指定了可视区域的大小和形状。对于正投影与透视投影这两种不同的投影类型,它们分别有各自的用途。

 

正投影

         它适用于2D图形,如文本、建筑画图等。在它的应用场合,我们希望在屏幕上展示准确的物体大小和度量。

 

OpenGL中的投影使用

透视投影

         它使用透视除法,对距离观察者较远的物体进行缩短和收缩。由于可视区域前端和后端的宽度度量方法并不同样,导致两个逻辑大小同样的物体,当它们分别位于可视区域的前面和后面时,前者看上去要比后者大一些。

         下图展示了*截头体(frustum)所定义的透视投影,它的观察方向是从狭窄端到宽阔端。工具函数gluPerspective能够方便的定义一个*截头体:

      

         void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far);

        

         參数 fovy表示垂直方向的视野角度,aspect表示宽度与高度的纵横比,near与far表示*端和远端裁剪*面之间的距离。

OpenGL中的投影使用

OpenGL中的投影使用

 

         以下的代码设置使用了透视投影,展示了一个由太阳(黄色)、地球(红色)、月亮(灰色)三者构成的运动系统。这是一个经典的嵌套变换的样例,我们使用矩阵堆栈将一个物体依据还有一个物体进行变换,执行结果如图所看到的:

OpenGL中的投影使用

OpenGL中的投影使用

/* 程序清单 4-3

 * 2014/5/18

 */

#include <glut.h>

#include <math.h>

 

// 旋转的步进值

static float fMoonRot =0.0f;

static float fEarthRot= 0.0f;

 

// 设置渲染状态

void SetupRC()

{

         // 设置清除窗体的颜色(黑色背景)

         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

         // 设置画图颜色为绿色

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

         // 打开深度測试

         glEnable(GL_DEPTH_TEST);

}

 

// 绘制场景(显示回调函数)

void RenderScene()

{

         // 用当前的清除颜色清除窗体

         glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);

         // 保存矩阵状态(模型视图矩阵)

         glMatrixMode(GL_MODELVIEW);

         glPushMatrix();

         // *移坐标系,注意是相对于视觉坐标的位置

         glTranslatef(0.0f, 0.0f, -300.0f);

 

         // 绘制太阳

         glColor3ub(255, 255, 0);

         glutSolidSphere(15.0f, 15, 15);

         // 旋转坐标系,累加效果

         glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f);

 

         // 绘制地球

         glColor3ub(255, 0, 0);

         // *移坐标系,累加效果

         glTranslatef(105.0f, 0.0f, 0.0f);

         // 设置地球的旋转步进

         fEarthRot += 5.0f;

         if(fEarthRot > 360.0f) {

                  fEarthRot = 0.0f;

         }

         glutSolidSphere(15.0f, 15, 15);

 

         // 绘制月球

         glColor3ub(200, 200, 200);

         // 旋转坐标系,累加效果

         glRotatef(fMoonRot, 0.0f, 1.0f, 0.0f);

         // *移坐标系,累加效果

         glTranslatef(30.0f, 0.0f, 0.0f);

         // 设置月亮的旋转步进

         fMoonRot += 15.0f;

         if(fMoonRot > 360.0f) {

                  fMoonRot = 0.0f;

         }

         glutSolidSphere(6.0f, 15, 15);

 

         // 恢复矩阵状态(当前坐标系与视觉坐标重合)

         glPopMatrix();

 

         // 交换缓冲区,显示画面

         glutSwapBuffers();

}

 

// 当窗体大小改变时由GLUT函数库调用

void ChangeSize(GLsizei w, GLsizei h)

{

         // 窗体的纵横比

         GLfloat fAspect;

         // 防止被0

         if (0== h) {

                  h = 1;

         }

         // 将视口设置为窗体的大小

         glViewport(0, 0, w, h);

         // 计算窗体的纵横比

         fAspect = (GLfloat)w / (GLfloat)h;

         // 设置当前操作的矩阵为投影矩阵

         glMatrixMode(GL_PROJECTION);

         glLoadIdentity();

         // 定义*截头体, 45度视野,*、远*面为1.0425.0

         gluPerspective(45.0f,fAspect, 1.0, 425.0);

         // 设置当前操作的矩阵为模型视图矩阵

         glMatrixMode(GL_MODELVIEW);

         glLoadIdentity();

}

 

// 计时器函数,每秒触发10次窗体重绘事件

void TimerFunc(intvalue)

{

         glutPostRedisplay();

         glutTimerFunc(100, TimerFunc, 1);

}

 

int main(int argc,char *argv[])

{

         // 传递命令行參数,并对GLUT函数库进行初始化

         glutInit(&argc, argv);

         // 设置创建窗体时的显示模式(双缓冲区、RGB颜色模式)

         glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

         // 设置窗体的初始大小

         glutInitWindowSize(480, 320);

         // 创建窗体

         glutCreateWindow(“Bounce”);

         // 设置显示回调函数

         glutDisplayFunc(RenderScene);

         // 设置当窗体的大小发生变化时的回调函数

         glutReshapeFunc(ChangeSize);

         // 设置计时器函数

         glutTimerFunc(100, TimerFunc, 1);

         // 设置渲染状态

         SetupRC();

         // 启动GLUT框架的执行,一经调用便不再返回,直到程序终止

         glutMainLoop();

 

         return0;

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/118963.html原文链接:https://javaforall.net

(0)
上一篇 2021年11月28日 下午7:00
下一篇 2021年11月28日 下午8:00


相关推荐

  • Mybatis分页查询[通俗易懂]

    Mybatis分页查询[通俗易懂]分页查询作为数据库交互最常用的几种操作之一,在日常开发中是非常常见的,比如前段请求需要一个分页的列表,往往有两种方式,一是把所有的数据都给到前段,前段分页。另外一种方式是前端通过传分页信息给后端,后端查询时进行分页,并将相应页的数据返给前端。第一种方式如果数据规模比较小的情况下可以使用,如果数据量较大,对内存、网络传输的消耗都是非常大的,所以实际开发中一般很少使用。第二种方式是后端进行分页,后端分…

    2022年6月2日
    101
  • pat乙级1002_PAT甲级

    pat乙级1002_PAT甲级题目链接实现#include&lt;iostream&gt;#include&lt;cstdio&gt;usingnamespacestd;//得到最大公因子intgcd(inta,intb) { returnb==0?a:gcd(b,a%b);}//最小公倍数intlcm(inta,intb){ returna/gcd(…

    2022年10月21日
    5
  • python—各种常用函数及库

    python—各种常用函数及库列表 list1 append x nbsp nbsp nbsp nbsp nbsp 将 x 添加到列表末尾 list1 sort nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 对列表元素排序 list1 reverse nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 将列表元素逆序 list1 index x nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 返回第一次出现元素 x 的索引值 list1 insert i x nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 在位置 i 处插入新元素 xlist1 count x nbsp

    2026年3月19日
    2
  • strsep的作用

    strsep的作用在下面这个code中通过strsep将p表示的字符串一“,”分开,例如12,34,56.会先返回12,然后是34,最后是56while((id=strsep(&p,”,”)))我们看看strsep的实现char*strsep(char**s,constchar*ct){   char*sbegin=*s;   char*end;  

    2025年6月26日
    4
  • 视频识别分类算法–MASK-RCNN框架[通俗易懂]

    视频识别分类算法–MASK-RCNN框架[通俗易懂]基础内容

    2022年5月3日
    47
  • 如何将InputStream转换为String

    2019独角兽企业重金招聘Python工程师标准>>>…

    2022年4月17日
    189

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号