回 帖 发 新 帖 刷新版面

主题:[原创]OpenGL入门学习——第十六课

现在即将放出的是第十六课的内容。

首先还是以前课程的连接:
[url=http://www.programfan.com/club/showbbs.asp?id=184355]第一课,编写第一个OpenGL程序[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=184525]第二课,绘制几何图形[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=184769]第三课,绘制几何图形的一些细节问题[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=185032]第四课,颜色的选择[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=196017]第五课,三维的空间变换[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=196231]第六课,动画的制作[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=218828]第七课,使用光照来表现立体感[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=219518]第八课,使用显示列表[/url]
[url=http://www.programfan.com/club/showbbs.asp?id=224877]第九课,使用混合来实现半透明效果[/url]
[url=http://www.programfan.com/club/post-227694.html]第十课,BMP文件与像素操作[/url]
[url=http://www.programfan.com/club/post-244703.html]第十一课,纹理的使用入门[/url]
[url=http://bbs.pfan.cn/post-252901.html]第十二课,OpenGL片断测试[/url]
[url=http://bbs.pfan.cn/post-275218.html]第十三课,OpenGL是一个状态机[/url]
[url=http://bbs.pfan.cn/post-275219.html]第十四课,OpenGL版本和OpenGL扩展[/url]
[url=http://bbs.pfan.cn/post-275223.html]第十五课,从“绘制一个立方体”来看OpenGL的进化过程[/url]
第十六课,在Windows系统中显示文字  ——→  [color=0000FF]本次课程的内容[/color]

内容超多的一课!不过我想精彩的程度也一定不会让大家失望。大家不妨先浏览一下课程里的图片:)。

[color=FF0000]2008-06-10 修改了附件[/color]
增加了两个文件,showline.c, showtext.c。分别为第二个和第三个示例程序的main函数相关部分。
在ctbuf.h和textarea.h最开头部分增加了一句#include <stdlib.h>
附件中一共有三个示例程序:
第一个,飘动的“曹”字旗。代码为:flag.c, GLee.c, GLee.h
第二个,带缓冲的显示文字。代码为:showline.c, ctbuf.c, ctbuf.h, GLee.c, GLee.h
第三个,显示歌词。代码为:showtext.c, ctbuf.c, ctbuf.h, textarea.c, textarea.h, GLee.c, GLee.h
其中,GLee.h和GLee.c可以[url=http://www.opengl.org/sdk/libs/GLee/GLee5_21.zip]从网上下载[/url],因此这里并没有放到附件中。在编译的时候应该将这两个文件和其它代码文件一起编译。

=====================未完,请勿跟帖=====================

回复列表 (共106个回复)

61 楼

这课是不是最后一课了? 是吗

62 楼

楼主辛苦了

63 楼

为了作者的这份教程注册了!首先要谢谢作者。
我是一个新手 刚开始学OpenGL,想请问一个问题:
OpenGL可以将显存上的数据不调回主内存直接显示出来吗?
例如一幅24位bmp图,将此图数据存入显存中后可以直接显示出来吗?如果可以的话是不是就不用将bmp图的数据调回主存再写个信息头再显示了
谢谢!

64 楼

你好!简单的说,显示显存的数据当然是可以的,并且比显示内存中的数据更加方便。
OpenGL把图片作为纹理存储,而一般的实现都是把纹理放到显存里面。要把图片显示出来的话,直接显示这幅纹理就可以了。

65 楼


谢谢。这么说,我是要学学你关于纹理那部分的教程罗

66 楼


真的非常感谢楼主!你讲得非常好。我现在正在上图形学的课,老师几乎不给我们讲编程方面的东西,讲好多理论。虽然我现在只看到你的课的第二课,但我还会继续学完的。

67 楼

lz能不能将一下VBO PBO和FBO的问题呢?
   我知道PBO是像素缓存的意思,想请问:假设我创建了一个PBO缓存空间,是不是往里面写像素值就可以在屏幕上显示出来了?若是这样的话,写像素值的时候是RGB三通道各8位这样写进去吗,还是应该怎么样?
   谢谢!

68 楼

多谢楼主!

69 楼

[quote]lz能不能将一下VBO PBO和FBO的问题呢?
我知道PBO是像素缓存的意思,想请问:假设我创建了一个PBO缓存空间,是不是往里面写像素值就可以在屏幕上显示出来了?若是这样的话,写像素值的时候是RGB三通道各8位这样写进去吗,还是应该怎么样?[/quote]

应该纠正一下:直接操作缓存不等于直接把像素画在屏幕上,也不等于直接操作显示器。
简单的想想:现代的显卡一般至少有数百M的显存了,但是显示时需要的数据一般只有1600x900x4 = 5760000字节,也就是不到6M。因此,不是所有的显存都是直接存放“显示在屏幕上的像素”数据的。修改这些数据并不会直接对屏幕上的像素产生任何影响。
我觉得具体的显示过程是这样的:OpenGL进行所谓的“绘制”,仅仅是把像素数据填写到缓冲里面,然后由系统按照缓冲中的实际内容去操作屏幕,进行实际的显示。OpenGL本身是没有“屏幕”这个概念的。

如果确实需要修改显示在屏幕上的像素,则只要修改缓冲的对应数据即可。如果是单缓冲模式,则应该修改前缓冲区;如果是双缓冲模式,则应该修改后缓冲区。
先用glDrawBuffer设置当前操作的缓冲区,然后用glRasterPos*系列函数或者glWindowPos*系列函数,制定要绘制的位置,最后用glDrawPixels即可进行绘制。(参见第十课)
一般认为glDrawPixels函数速度较慢,所以建议是把像素装到纹理中,然后把这个纹理显示出来。

VBO, PBO, FBO,虽然都叫BO(Buffer Object),但是区别还是比较明显的。
VBO, PBO,这两者比较相似,主要就是对内存操作的增强——原来需要传入指针的函数,有了VBO和PBO,现在就可以用绑定一个buffer然后传入一个offset来做了(除了功能方面的增强,性能方面优化的余地也更大)。唯一的区别就是VBO用于顶点数据、索引数据,而PBO用于像素数据。
如果您创建了一个VBO或者PBO,其实就是有了一个容纳数据的容器,然后就可以用glBufferData, glMapBuffer等函数,来指定数据的大小以及内容了。这个空间中的数据是由我们自由操作的,OpenGL不会约束我们必须要RGB各占一个字节,或者一个像素占两个字节。一切都是由我们自己决定,就像是普通的内存一样。另外,注意这里提到的buffer不一定是显存,它可以是显存、系统内存或者其它,由OpenGL的具体实现来决定。
对于FBO,它有点不同。它只是把对数据的操作转向到我们指定的那个对象。可以把它想象成一个传话筒,把“修改数据”的命令传递到它指向的那个对象。指向的对象可以是RenderBuffer,也可以是纹理。FBO本身并不分配数据空间,它只是使用RenderBuffer或者纹理的数据。

最近我也没有写这方面的程序,有点手生了。暂时不能提供示例代码。请见谅。
楼主可以看看OpenGL官方的链接:(可以先看其中的Usage Examples)
http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt
http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
或者也可以在网上搜索相关的示例代码。

70 楼

[quote][quote]lz能不能将一下VBO PBO和FBO的问题呢?
我知道PBO是像素缓存的意思,想请问:假设我创建了一个PBO缓存空间,是不是往里面写像素值就可以在屏幕上显示出来了?若是这样的话,写像素值的时候是RGB三通道各8位这样写进去吗,还是应该怎么样?[/quote]

应该纠正一下:直接操作缓存不等于直接把像素画在屏幕上,也不等于直接操作显示器。
简单的想想:现代的显卡一般至少有数百M的显存了,但是显示时需要的数据一般只有1600x900x4 = 5760000字节,也就是不到6M。因此,不是所有的显存都是直接存放“显示在屏幕上的像素”数据的。修改这些数据并不会直接对屏幕上的像素产生任何影响。
我觉得具体的显示过程是这样的:OpenGL进行所谓的“绘制”,仅仅是把像素数据填写到缓冲里面,然后由系统按照缓冲中的实际内容去操作屏幕,进行实际的显示。OpenGL本身是没有“屏幕”这个概念的。

如果确实需要修改显示在屏幕上的像素,则只要修改缓冲的对应数据即可。如果是单缓冲模式,则应该修改前缓冲区;如果是双缓冲模式,则应该修改后缓冲区。
先用glDrawBuffer设置当前操作的缓冲区,然后用glRasterPos*系列函数或者glWindowPos*系列函数,制定要绘制的位置,最后用glDrawPixels即可进行绘制。(参见第十课)
一般认为glDrawPixels函数速度较慢,所以建议是把像素装到纹理中,然后把这个纹理显示出来。

VBO, PBO, FBO,虽然都叫BO(Buffer Object),但是区别还是比较明显的。
VBO, PBO,这两者比较相似,主要就是对内存操作的增强——原来需要传入指针的函数,有了VBO和PBO,现在就可以用绑定一个buffer然后传入一个offset来做了(除了功能方面的增强,性能方面优化的余地也更大)。唯一的区别就是VBO用于顶点数据、索引数据,而PBO用于像素数据。
如果您创建了一个VBO或者PBO,其实就是有了一个容纳数据的容器,然后就可以用glBufferData, glMapBuffer等函数,来指定数据的大小以及内容了。这个空间中的数据是由我们自由操作的,OpenGL不会约束我们必须要RGB各占一个字节,或者一个像素占两个字节。一切都是由我们自己决定,就像是普通的内存一样。另外,注意这里提到的buffer不一定是显存,它可以是显存、系统内存或者其它,由OpenGL的具体实现来决定。
对于FBO,它有点不同。它只是把对数据的操作转向到我们指定的那个对象。可以把它想象成一个传话筒,把“修改数据”的命令传递到它指向的那个对象。指向的对象可以是RenderBuffer,也可以是纹理。FBO本身并不分配数据空间,它只是使用RenderBuffer或者纹理的数据。

最近我也没有写这方面的程序,有点手生了。暂时不能提供示例代码。请见谅。
楼主可以看看OpenGL官方的链接:(可以先看其中的Usage Examples)
http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt
http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
或者也可以在网上搜索相关的示例代码。[/quote]
十分感谢lz耐心的回答!我先学习一下,有问题再咨询。谢谢!

我来回复

您尚未登录,请登录后再回复。点此登录或注册