zoukankan      html  css  js  c++  java
  • OpenGL中移动单位中的‘单位’指什么

    opengl 比如 用到glm::translate(x,y,z) 表示 移动x,y,z个单位, 那么这个这个单位是指什么呢?这里的单位不是指像素,是根据投影矩阵的变化而变化的,默认情况下投影矩阵Projection是单位矩阵,那么 宽和高的屏幕范围为 (-1.0f,1.0f),0.0表示的是屏幕的中间,这就是为什么在我们看到的一些例子中,如果仅仅是为了展示绘制三角形或者四边形,没有涉及到视图矩阵和投影矩阵的时候,设置(-0.5,-0.5) (0.5,-0.5) (0.5,0.5) (-0.5,0.5)这种坐标。因为此时边框范围就是 (-1.0f,1.0f)。

    但是当我们 设置了投影矩阵的时候,比如用glm库中的 glm::perspective(60.0f, width / height, 10.0f, 1000.0f); 这个函数返回一个 投影矩阵,然后 投影矩阵 * 模型视图矩阵之后所得到的坐标并投影到 屏幕中的时候,就会模拟出我们眼睛看到的物体的效果。60指的是我们眼睛看到的范围的度数, width / height 为宽高比,这个和屏幕宽高比一致,这样绘制出的图形不会拉伸变形。0.1f和1000.0f这里 是指离我们眼睛的 裁剪体距离,这里也是指Z方向的单位,不是像素,比如我们如果设置某个点为(x,y, 8.0f),在裁剪体之外,那么是不会绘制到屏幕中的。

    那么x,y 的单位是怎么定义的呢,比如我们想绘制 一个小球让他的中心点位于 屏幕中1/4的位置,应该如何设置。如果我们没有设置投影矩阵,那么让坐标为(-0.25,-0.25,0)就可以。如果我们需要设置投影矩阵和视图矩阵(就是根据‘照相机’的位置返回一个矩阵,然后我们世界坐标和这个相机相乘,模拟以相机为原点进行观察物体的效果),那么在点的不同的Z坐标的情况下,他们的单位是不一样的。透视投影会通过z轴的不同,显示近大远小的效果,比如两个点(-10,0,-10)和(-10,0,-5)通过透视投影之后,前者会比后者呈现的图像大。所以如果想让2个点投射到 近裁剪面相同的位置,让他们重合,方法之一是把后者 改为(-5,0,-5),让他们比例一样,这样投射到屏幕中之后位置就相同了。从这里可以看出,2个点各自的单位不一样了,虽然呈现在屏幕的位置一样。

    比如在cocos中,通过设置裁剪矩阵和视图矩阵的距离和角度,让屏幕上z坐标为0的点的‘单位’恰好为 设计分辨率的单位 ,这样我们可以忽略实际分辨率,直接以设计分辨率为单位调整坐标,得到实际绘制到屏幕的效果。

    再举一个例子,参考一个论坛的例子

    如果你想在距离屏幕中心的1/4的位置画一个三角形,你有N种方法来实现。如syy64所说的,当你在距离屏幕中心1/4处看到一个三角形的时侯,实际上是一个空间的三角形投影到了屏幕上。

    当你在OpenGL程序中定义了投影之后,glTranslatef的移动单位是可以与屏幕像素值发生关系的。举个例子,我定义透视投影如下:
    gluPerspective(45,w/h,0.1,1000);

    这时,屏幕相当于近裁剪面,视点在屏幕向外1分米的地方。当然注意!这里1分米跟我们现实世界的1分米还是不一样的,不是说,你把眼睛凑到屏幕前1分米就相当于视点所在位置了。那么,这里所定义的1分米到底是个什么概念呢?它实际上是虚拟世界坐标系中的1分米。

    我们看第一个参数,45。表明视野在竖直方向的张角是45度,于是我们可以算出近裁剪面的高度:h=2*tan(22.5*PI/180)*0.1=0.082842712。
    也就是说,近裁剪面约为8.3厘米高。换句话说,虚拟世界中的8.3厘米,就相当于我们的屏幕高,如果你的显示器是1024*768分辨率的话,那么虚拟世界中的8.3厘米就等价于768像素。这样,就将虚拟坐标单位和屏幕像素值建立起了联系。

    如果你要在距离屏幕中心1/4的地方(假设为水平距离)画一个物体的话,就相当于在距离中心点1/4*1024=256像素的地方绘图。这时,在近裁剪面上,相当于移动了256/768*8.3=2.76厘米。
    在虚拟三维世界中的任何物体,只要其形心的x坐标和z坐标满足如下关系:
    |x|*0.1/|z|=0.0276,并且处于视锥之内的话,都将被画在距离屏幕中心1/4的地方。 

  • 相关阅读:
    使用memset()要注意
    UPC快速学习笔记之Collective Operations
    二叉搜索树(结点添加、后继搜索、前驱搜索、结点删除)
    十分愚蠢的错误记录(C++创建对象时new的问题)
    BFS和DFS分别用于有向图和无向图的一点心得和总结
    不要在if判断语句中同时声明变量,注意在if中同时赋值和判断的优先级
    C++内存泄漏姿势之——eof()和delete释放内存
    C++中"was not declared in this scope"问题记录;以及通过正则表达式提取文件中数字的方法
    论fork()函数的进阶使用
    页面的修改、添加,以及验证控件的常见应用
  • 原文地址:https://www.cnblogs.com/xiaonanxia/p/9324746.html
Copyright © 2011-2022 走看看