OPENGL 矩阵变换的理解 & OpenGL 2D坐标定位心得

这两天一直在思考如何在OpenGL底下对二维的屏幕坐标进行定位。很可惜OpenGL里并没有直接定位的函数,似乎所有的函数都是把输入一个三维的坐标,然后返回这个三维坐标在当前变换矩阵下对应屏幕上的点。不可否认这个东西很有用,比如在敌人身上冒出个伤害值什么的就非此不可。但我现在需要的只是在屏幕上某个固定的位置显示事先设计好的点阵字,那就不是那么好办了……


开始的时候用glLoadIdentity初始化矩阵之后用glRasterPos2i(0,0)定位到屏幕中心,再用glBitmap的第五、六个参数来偏移到目的地。但一直觉得心虚……要知道分辨率都是偶数的,也就是说“中心”对应的二维坐标很可能是因系统而异的。在一个系统下正常的画面到另一个系统可能就歪了。虽然能够在特定条件下满足要求,但这样不健壮的代码总是一个麻烦……


后来看到一个网站上说可以用gluOrtho2D把投影设定成正投影的方法来定位二维坐标:


    gluOrtho2D(0, 639, 0, 479);


这样一来,屏幕的左下角就是坐标(0,0),右上角就是(639,479)。然后再用glRasterPos2i来定位就可以了。


然而我尝试的时候总是失败,总是定位到无效的位置导致接下来的点阵字根本就不显示。这个问题大约困扰了我一天的时间。我想方法应该没有错,应该只是有一些基础的代码,该文的作者认为每个OpenGL程序员都应该了解的代码被省略了。于是我去查一本很厚的书,把关于视图的部分好好看了看,终于发现了问题的关键。


OpenGL的变换矩阵分为投影矩阵(GL_PROJECTION)和视图/模型矩阵(GL_MODELVIEW)。(暂不涉及纹理矩阵GL_TEXTURE)使用gluOrtho2D或者gluPerspective等改变投影矩阵的函数之前应该先用glMatrixMode(GL_PROJECTION)将当前矩阵模式设置为投影矩阵,然后glOrtho等函数才能正常地去改变投影矩阵。


换句话说OpenGL里无论是gluPerspective这样的(理解上)改变投影矩阵的函数,还是glTranslatef这样的(理解上)改变视图/模型矩阵的函数,其本质都是根据函数的参数算出一个矩阵,然后与当前矩阵相乘。至于当前矩阵是哪个矩阵,则由glMatrixMode来指定。


了解了问题所在,就很容易写出正确的代码:


    //在此之前已经处理完全部三维画面
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, 639, 0, 479);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRasterPos2i(x, y); //x与y是坐标,左下角为(0,0)
    //从这里开始处理二维画面


以上是窗口大小为640x480的情况。可以将代码写得更加健壮一些。设cx为窗口宽度,cy为窗口高度,则代码相应为:


    //在此之前已经处理完全部三维画面
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, cx-1, 0, cy-1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRasterPos2i(x, y); //x与y是坐标,左下角为(0,0)
    //从这里开始处理二维画面


其实走了这么多弯路,估计根本原因还是在于我的OpenGL是自学的,这儿学一点那儿学一点,难免有莫名其妙的漏洞,于是就时刻受堵了。仔细一想,我有很多东西都是这样东学一点西学一点的,不成系统。以后还是应该脚踏实地更加踏实地学习,争取学分积上85。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
`glCopyTexImage2D`是OpenGL中的一个函数,用于将当前帧缓冲区中的像素数据复制到一个新的纹理对象中。它可以用于实现屏幕截图、渲染到纹理等功能。 函数原型如下: ```cpp void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); ``` 参数解释: - `target`:指定纹理目标,可以是`GL_TEXTURE_2D`或`GL_TEXTURE_CUBE_MAP_POSITIVE_X`等等。 - `level`:指定要生成的纹理的细节级别,一般为0。 - `internalformat`:指定纹理的内部格式,如`GL_RGBA`、`GL_RGB8`等。 - `x`、`y`:指定源像素矩形区域在窗口坐标系中的起始位置。 - `width`、`height`:指定源像素矩形区域的宽度和高度。 - `border`:指定边框的宽度,一般为0。 调用该函数后,OpenGL会将指定区域内的像素数据复制到当前绑定的纹理对象中,从而创建一个新的纹理图像。这个函数可以用于将当前帧缓冲区中的内容作为纹理,供后续的渲染使用。 注意事项: - 在调用该函数前,需要先创建一个纹理对象,并将其绑定为当前纹理。 - 被复制的像素数据会被按照指定的内部格式存储到纹理中,因此需要确保纹理对象的格式与复制的像素数据格式匹配。 - 复制的像素数据可以是整个帧缓冲区,也可以是其中的一部分。 需要注意的是,OpenGL已经不再是最新的图形API,现在已经有了更先进的API如Vulkan和DirectX 12。如果你是在新的项目中使用图形API,可以考虑使用这些更先进的API。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值