opengl 订阅
OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来绘制从简单的图形比特到复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。OpenGL的高效实现(利用了图形加速硬件)存在于Windows,部分UNIX平台和Mac OS。这些实现一般由显示设备厂商提供,而且非常依赖于该厂商提供的硬件。开放源代码库Mesa是一个纯基于软件的图形API,它的代码兼容于OpenGL。但是,由于许可证的原因,它只声称是一个“非常相似”的API。OpenGL规范由1992年成立的OpenGL架构评审委员会(ARB)维护。ARB由一些对创建一个统一的、普遍可用的API特别感兴趣的公司组成。根据OpenGL官方网站,2002年6月的ARB投票成员包括3Dlabs、Apple Computer、ATI Technologies、Dell Computer、Evans & Sutherland、Hewlett-Packard、IBM、Intel、Matrox、NVIDIA、SGI和Sun Microsystems,Microsoft曾是创立成员之一,但已于2003年3月退出。 展开全文
OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来绘制从简单的图形比特到复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。OpenGL的高效实现(利用了图形加速硬件)存在于Windows,部分UNIX平台和Mac OS。这些实现一般由显示设备厂商提供,而且非常依赖于该厂商提供的硬件。开放源代码库Mesa是一个纯基于软件的图形API,它的代码兼容于OpenGL。但是,由于许可证的原因,它只声称是一个“非常相似”的API。OpenGL规范由1992年成立的OpenGL架构评审委员会(ARB)维护。ARB由一些对创建一个统一的、普遍可用的API特别感兴趣的公司组成。根据OpenGL官方网站,2002年6月的ARB投票成员包括3Dlabs、Apple Computer、ATI Technologies、Dell Computer、Evans & Sutherland、Hewlett-Packard、IBM、Intel、Matrox、NVIDIA、SGI和Sun Microsystems,Microsoft曾是创立成员之一,但已于2003年3月退出。
信息
外文名
Open Graphics Library
平    台
Windows、类Unix、Linux、MacOS
是否开源
软件类别
开放库文件
介    绍
三维图形处理库,属于工业标准
中文名
开放图形库(英文Open Graphics Library的缩写)
最近更新日期
2018-07-30
OpenGL简介
OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来从简单的图形比特绘制复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟实境、科学可视化程序和电子游戏开发。OpenGL的高效实现(利用了图形加速硬件)存在于Windows,部分UNIX平台和Mac OS。这些实现一般由显示设备厂商提供,而且非常依赖于该厂商提供的硬件。开放源代码库Mesa是一个纯基于软件的图形API,它的代码兼容于OpenGL。但是,由于许可证的原因,它只声称是一个“非常相似”的API。OpenGL规范由1992年成立的OpenGL架构评审委员会(ARB)维护。ARB由一些对创建一个统一的、普遍可用的API特别感兴趣的公司组成。根据OpenGL官方网站,2002年6月的ARB投票成员包括3Dlabs、Apple Computer、ATI Technologies、Dell Computer、Evans & Sutherland、Hewlett-Packard、IBM、Intel、Matrox、NVIDIA、SGI和Sun Microsystems,Microsoft曾是创立成员之一,但已于2003年3月退出。
收起全文
精华内容
下载资源
问答
  • OpenGL

    万人学习 2016-12-24 20:43:02
    课程涵盖了OpenGL开发的方方面面,对开发中经常用到的开发知识点进行讲解,从实战的角度进行编码设计. 第1章-环境建立 第2章-基础图元 第3章-三维世界 第4章-纹理多彩世界 第5章-显存的分配-优化 第6章-场景控制...
  • OPenGL

    千次下载 热门讨论 2008-02-27 16:04:38
    OPenGL OPenGL
  • opengl

    千次阅读 2015-05-02 14:32:44
    1.1 Opengl简介 2 1.2 openGl 的工作方式 3 1.2.1 Opengl 体系结构 3 1.2.2 openGl 流水线 3 1.2.3 OpenGl状态机 4 1.3 OpenGl 操作步骤 4 1.4 OpenGl 组成 4 1.5 OpenGl 数据类型 5 1.6 Open
     penGl 基本框架    2
    1.1 Opengl简介    2
    1.2 openGl 的工作方式    3
    1.2.1 Opengl 体系结构    3
    1.2.2 openGl 流水线    3
    1.2.3 OpenGl状态机    4
    1.3 OpenGl 操作步骤    4
    1.4 OpenGl 组成    4
    1.5 OpenGl 数据类型    5
    1.6 OpenGl 函数命名约定    5
    2. Linux Mesa 安装    6
    2.1 下载Mesa软件包    6
    2..2 For DRI and hardware acceleration    7
    2.3. 整理安装步骤    8
    2.3.1 下载mesalib 和gult包    8
    2.3.2 安装其他包    9
    2.3.3 安装dri2proto 和 libdrm, pixman    9
    2.3.4. 编译安装    10
    2.4 安装glut    11
    3. OpenGL 简介o    11
    3.1 什么是OpenGL    11
    3.2 OpenGL 一些概念    12
    3.3 OpenGL是一个状态机    13
    3.4 OpenGl 渲染管线    13
    3.4.1 显示列表    14
    3.4.2 求值器    14
    3.4.3 基于顶点的操作    14
    3.4.4 图元装配    14
    3.4.5 像素操作    15
    3.4.6 纹理装配    15
    3.4.7 光栅化    15
    3.4.8 片段操作1    16
    3.5 动画    16
    3.5.1 暂停刷新    16
    3.5.2 动画 = 重绘 + 交换    17
    3.6 OpenGl 废弃机制    17
    4. 状态管理和绘制几何物体    18
    4.1 绘图工具箱    18
    4.1.1 清除窗口    18
    4.1.2 指定颜色    19

    1 openGl 基本框架
    1.1 Opengl简介





    1.2 openGl 的工作方式
    1.2.1 Opengl 体系结构


    1.2.2 openGl 流水线


    1.2.3 OpenGl状态机


    1.3 OpenGl 操作步骤


    1.4 OpenGl 组成




    1.5 OpenGl 数据类型


    1.6 OpenGl 函数命名约定


    2. Linux Mesa 安装
    2.1 下载Mesa软件包
    1)进入http://www.mesa3d.org/download.html 下载 MesaLib-8.0.5.tar.gz,
    MesaGLUT-7.9.2.tar.gz

        2)把两个解压到同一个文件里,然后在shell里cd 到解压目录
    运行ubuntu@ubuntu:/opt/OpenGl/Mesa-8.0.5$ ./configure
    出现这个错误:configure: error: makedepend is required to build Mesa
    安装xutils-dev
    ubuntu@ubuntu:/opt/OpenGl/Mesa-8.0.5$

     sudo apt-get install xutils-dev

        3)./configure
    出现错误:error: Package requirements (glproto >= 1.4.14) were not met:
    No package 'glproto' found

     (   在网址http://packages.ubuntu.com/source/precise/x11/中,找到x11proto-gl (1.4.14-2),然后点击进去下载x11proto-gl_1.4.14.orig.tar.gz,
    安装库:a) ./configure b) make -j4 c) make install )

    解决方法:sudo apt-get install x11proto-gl-dev

        4)./configure
    error: Package requirements (dri2proto >= 2.6) were not met:
    No package 'dri2proto' found

       安装库: sudo apt-get install x11proto-dri2-dev
        
        5)./configure
    error: Package requirements (x11 xext xdamage xfixes x11-xcb xcb-glx) were not met:
    No package 'xdamage' found
    No package 'xfixes' found
    No package 'x11-xcb' found
    No package 'xcb-glx' found

        安装库:sudo apt-get install libx11-xcb-dev
                sudo apt-get install libxcb-glx0
                sudo apt-get install libxcb-glx0-dev
    sudo apt-get install libxdamage-dev

        6)./configure
           configure: error: Expat required for DRI.    
    见2.2
    2..2 For DRI and hardware acceleration


    1下载libdrm-2.4.35.tar.gz

    解压后进入libdrm目录
    1) 运行./configure
    出现:error: Package requirements (pciaccess >= 0.10) were not met:
    No package 'pciaccess' found

    安装:
    sudo apt-get install libpciaccess-dev

    2) 运行./configure生成makefile
    3)make
    4)make install

    2下载dri2proto-2.8.tar.gz
    解压后进入dri2proto目录
     1)./configure
    2) make install

    3 安装xorg-x11-serve
    1)从下面网址下下载xorg-x11-serve

    sudo apt-get install xserver-xorg-dev

    (http://ftp.isu.edu.tw/pub/Linux/Ubuntu/ubuntu/pool/main/x/xorg-server/
    2)解压后进入解压目录
    ./configure
    configure: error: Package requirements (pixman-1 >= 0.15.20) were not met:

    No package 'pixman-1' found
    3) 安装pixman
    http://packages.ubuntu.com/oneiric/libpixman-1-0 下载pixman
     ./configure
    make
    sudo make install

    4)./configure
    configure: error: Package requirements (xf86driproto >= 2.1.0) were not met:
    sudo apt-get install x11proto-xf86dri-dev

    5) ./configure
    checking for SHA1 implementation... configure: error: No suitable SHA1 implementation found

    sudo apt-get install openssl )

    4. 进入Mesa目录
    ./configure
    configure: error: Expat required for DRI

    sudo apt-get install libexpat-dev

    5. ./configure

    configure: error: LLVM is required to build Gallium R300 on x86 and x86_64

    sudo apt-get install llvm

    2.3. 整理安装步骤
    2.3.1 下载mesalib 和gult包
    进入http://www.mesa3d.org/download.html 下载 MesaLib-8.0.5.tar.gz,
    MesaGLUT-7.9.2.tar.gz

        2)把两个解压到同一个文件里

    2.3.2 安装其他包
    sudo apt-get install xutils-dev
    sudo apt-get install x11proto-gl-dev
    sudo apt-get install x11proto-dri2-dev
    sudo apt-get install libx11-xcb-dev
    sudo apt-get install libxcb-glx0
    sudo apt-get install libxcb-glx0-dev
    sudo apt-get install libxdamage-dev
    sudo apt-get install libpciaccess-dev
    sudo apt-get install xserver-xorg-dev
    sudo apt-get install x11proto-xf86dri-dev
    sudo apt-get install libexpat-dev
    sudo apt-get install llvm
    2.3.3 安装dri2proto 和 libdrm, pixman
    http://www.mesa3d.org/install.html
    下载


    1下载libdrm-2.4.35.tar.gz

    解压后进入libdrm目录
    1) 运行./configure
    2) 运行./configure生成makefile
    3)make
    4)make install

    2下载dri2proto-2.8.tar.gz
    解压后进入dri2proto目录
     1)./configure
    2) make install

    3. 安装pixman
    http://packages.ubuntu.com/oneiric/libpixman-1-0 下载pixman
     ./configure
    make
    sudo make install

    2.3.4. 编译安装
    进入解压的Mesa-8.0.5
    1)运行 ./configure
    prefix:          /usr/local
    exec_prefix:     ${prefix}
     libdir:          ${exec_prefix}/lib
     includedir:      ${prefix}/include

    2)编译Mesa
     make linux-x86

    3) 安装
    Make install

    4) 卸载
    sudo apt-get autoremove xutils-dev
    sudo apt-get autoremove x11proto-gl-dev
    sudo apt-get autoremove x11proto-dri2-dev
    sudo apt-get autoremove libx11-xcb-dev
    sudo apt-get autoremove libxcb-glx0
    sudo apt-get autoremove libxcb-glx0-dev
    sudo apt-get autoremove libxdamage-dev
    sudo apt-get autoremove libpciaccess-dev
    sudo apt-get autoremove xserver-xorg-dev
    sudo apt-get autoremove x11proto-xf86dri-dev
    sudo apt-get autoremove libexpat-dev
    sudo apt-get autoremove llvm

    #delete include and lib
    cd /usr/local
    #libdrm
    sudo rm -r include/libdrm
    sudo rm lib/libdrm*

    #dri2proto
    sudo rm -r include/libkms
    sudo rm lib/libkm*

    #pixman-1
    sudo rm -r include/pixman-1
    sudo rm lib/libpixman*

    #mesa
    sudo rm -r include/EGL
    sudo rm -r include/GL
    sudo rm -r include/KHR
    sudo rm -r include/VG
    sudo rm -r include/X11

    sudo rm lib/libEGL*
    sudo rm lib/libGL*
    sudo rm lib/libOpenVG*
    sudo rm lib/libOSMesa*

    2.4 安装glut
    sudo apt-get install freeglut3
    库路径:/usr/lib/i386-linux-gnu
    3. OpenGL 简介
    3.1 什么是OpenGL




    3.2 OpenGL 一些概念
    渲染:是计算机根据模型创建图像的过程。最终完成了渲染的图像是由屏幕上绘制的像素组成的。

    模型:根据几何图元创建的,也称为物体(object).几何图元包括点、直线和多边形等,它们是通过顶点(vertex)指定的。

    像素:显示硬件可以在屏幕的最小可视元素。(在内存中,和像素有关的信息(ep:像素的颜色))组成位平面的形式。

    位平面:是一块内存区域,保存了屏幕上每个像素的1个位的信息。(ep:它指定了一个特定像素的颜色中红色成分的强度)。
    位平面又可以组织成帧缓冲区(framebuffer)的形式,后者保存了图像硬件为了控制屏幕上所有像素的颜色和强度所需要的全部信息。

    3.3 OpenGL是一个状态机


    3.4 OpenGl 渲染管线



    3.4.1 显示列表


    3.4.2 求值器


    3.4.3 基于顶点的操作


    3.4.4 图元装配



    3.4.5 像素操作


    3.4.6 纹理装配


    3.4.7 光栅化


    3.4.8 片段操作


    3.5 动画




    3.5.1 暂停刷新
    如果帧率超过屏幕刷新率只会浪费图形处理的能力,因为监视器不能以这么快的速度更新,这样超过刷新率的帧率就浪费掉了。




    3.5.2 动画 = 重绘 + 交换


    3.6 OpenGl 废弃机制

    4. 状态管理和绘制几何物体


    4.1 绘图工具箱


    4.1.1 清除窗口





    在发送命令清除多个缓冲区之前,如果想使用并不是默认的RGBA值,深度值、累积值和模板索引值,就必须为每个缓冲区设置需要清除的值。

        glClearColor() 设置颜色缓冲区的值
        
        glClearDepth()设置深度缓冲区的值

        glClearIndex()设置清除相应缓冲区的颜色索引值

        glClearAccum() 设置累计累计缓冲区的颜色值

        glClearStencil()清除模板缓冲区的颜色值


    4.1.2 指定颜色
    OpenGL 程序员首先设置颜色或颜色方案,
    然后再绘制物体。
    在这种颜色方案被修改之前,所有的物体都用这种颜色方案进行绘制。

    为了设置颜色,可以使用glColor3f()函数。这个函数接受3个参数,它们都是0.0~1.0之间的浮点数,分别表示颜色的红、绿和蓝色成分。



    4.1.3 强制绘图完成







    4.2 顶点数组
    红宝书阅读笔记——缓冲区对象
    前面的顶点数组使得几何图元的显示方便了很多,但是如果每次都要向OPENGL发送一大块数据,而这数据其实并没有修改过,那么这传输就是冗余的。所以这里添加了缓冲区对象,将顶点数组存储在服务器端的缓冲区对象中。

    1. 创建缓冲区对象
    glGenBuffers(GLsizei n,GLuint *buffers) 任何非零的无符合整数都可以作为缓冲区对象的标识符使用。这个函数的作用就是向系统申请n个缓冲区,系统把这n个缓冲区的标识符都放进buffers数组中。还可以调用glIsBuffer()函数判断一个标识符是否正被使用。

    2. 激活缓冲区对象
    为了激活缓冲区对象,首先需要将它绑定。glBindBuffer(GLenum target, GLuint buffer)。target用于决定绑定的是顶点数据还是索引,关于这个函数的解释,书上第二章讲的很详细了。

    3. 用数据分配和初始化缓冲区对象
    glBufferData()用于在OPENGL服务器中分配内存建立缓冲区,并将客户机的内存复制到这个缓冲区对象。

    4. 更新缓冲区对象的数值
    当程序中的顶点坐标、颜色等数据发生了修改之后,需要修改对应的缓冲区数值。这里有两种方法可以完成此功能。

    glBufferSubData():直接用提供的数据替换绑定的缓冲区的数据子集。

    第二种方法更灵活些:
    首先用glMapBuffer()返回一个缓冲区指针,然后通过指针和下标对缓冲区对象做修改,
    最后调用glUnmapBuffer()取消对缓冲区的映射。

    5. 清除缓冲区对象
    glDeleteBuffers(GLsizei n,GLuint *buffers),完成了对缓冲区对象的操作之后,可以释放它的资源。
     
    当使用缓冲区对象存储顶点数组数据时,应在应用程序中增加几个步骤:

    1)生成缓冲区对象标识符(可选)。
    2)绑定缓冲区对象,确定它是用于存储顶点数据还是索引。
    3)请求数据的存储空间,并对这些数据元素进行初始化,
    下一个步骤可选。
    指定相对于缓冲区起始位置的偏移量,对诸如glVertexPointer()这样的顶点数组进行初始化。
    4)绑定适当的缓冲区对象,以用于渲染。
    5)使用适当的顶点数组渲染函数进行渲染,如glDrawArrays()或glDrawElements()等。
    流程图如下:

    over~

    展开全文
  • openGL

    千次阅读 2016-04-05 17:19:29
    OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库。 中文名开放图形库(英文Open...

    OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库。

    中文名
    开放图形库(英文Open Graphics Library的缩写)
    外文名
    Open Graphics Library
    平    台
    Windows、类Unix、Linux、MacOS
    是否开源
    最近更新日期
    2014年8月11日
    软件类别
    开放库文件

    基本介绍

    OpenGL™ 是行业领域中最为广泛接纳的 2D/3D 图形API, 其自诞生至今已催生了各种计算机平台及设备上的数千优秀应用程序。OpenGL™ 是独立于视窗操作系统或其它操作系统的,亦是网络透明的。在包含CAD、内容创作、能源娱乐、游戏开发制造业、制药业及虚拟现实等行业领域中,OpenGL™ 帮助程序员实现在 PC、工作站超级计算机等硬件设备上的高性能、极具冲击力的高视觉表现力图形处理软件的开发。
    OpenGL的前身是SGI公司为其图形工作站开发的IRIS GL。IRIS GL是一个工业标准的3D图形软件接口,功能虽然强大但是移植性不好,于是SGI公司便在IRIS GL的基础上开发了OpenGL。OpenGL的英文全称是“Open Graphics Library”,顾名思义,OpenGL便是“开放的图形程序接口”。虽然DirectX在家用市场全面领先,但在专业高端绘图领域,OpenGL是不能被取代的主角。
    OpenGL是个与硬件无关的软件接口,可以在不同的平台如Windows 95Windows NTUnixLinux、MacOS、OS/2之间进行移植。因此,支持OpenGL的软件具有很好的移植性,可以获得非常广泛的应用。由于OpenGL是图形的底层图形库,没有提供几何实体图元,不能直接用以描述场景。但是,通过一些转换程序,可以很方便地将AutoCAD、3DS/3DSMAX等3D图形设计软件制作的DXF和3DS模型文件转换成OpenGL的顶点数组
    在OpenGL的基础上还有Open Inventor、Cosmo3D、Optimizer等多种高级图形库,适应不同应用。其中,Open Inventor应用最为广泛。该软件是基于OpenGL面向对象的工具包,提供创建交互式3D图形应用程序的对象和方法,提供了预定义的对象和用于交互的事件处理模块,创建和编辑3D场景的高级应用程序单元,有打印对象和用其它图形格式交换数据的能力。
    OpenGL的发展一直处于一种较为迟缓的态势,每次版本的提高新增的技术很少,大多只是对其中部分做出修改和完善。1992年7月,SGI公司发布了OpenGL的1.0版本,随后又与微软公司共同开发了Windows NT版本的OpenGL,从而使一些原来必须在高档图形工作站上运行的大型3D图形处理软件也可以在微机上运用。1995年OpenGL的1.1版本面市,该版本比1.0的性能有许多提高,并加入了一些新的功能。其中包括改进打印机支持,在增强元文件中包含OpenGL的调用,顶点数组的新特性,提高顶点位置法线颜色、色彩指数、纹理坐标、多边形边缘标识的传输速度,引入了新的纹理特性等等。OpenGL 1.5又新增了“OpenGL Shading Language”,该语言是“OpenGL 2.0”的底核,用于着色对象、顶点着色以及片断着色技术的扩展功能。
    OpenGL 2.0标准的主要制订者并非原来的SGI,而是逐渐在ARB中占据主动地位的3DLabs。2.0版本首先要做的是与旧版本之间的完整兼容性,同时在顶点与像素及内存管理上与DirectX共同合作以维持均势。OpenGL 2.0将由OpenGL 1.3的现有功能加上与之完全兼容的新功能所组成(如图一)。借此可以对在ARB停滞不前时代各家推出的各种纠缠不清的扩展指令集做一次彻底的精简。此外,硬件可编程能力的实现也提供了一个更好的方法以整合现有的扩展指令。
    目前,随着DirectX的不断发展和完善,OpenGL的优势逐渐丧失,至今虽然已有3Dlabs提倡开发的2.0版本面世,在其中加入了很多类似于DirectX中可编程单元的设计,但厂商和用户的认知程度并不高,未来的OpenGL发展前景迷茫。

    发展历程

    1992年7月,SGI公司发布了OpenGL的1.0版本,随后又与微软公司共同开发了Windows NT版本的OpenGL,从而使一些原来必须在高档图形工作站上运行的大型3D图形处理软件也可以在微机上运用。
    1995年OpenGL的1.1版本面市,该版本较1.0性能提高许多,并加入了一些新的功能。包括提高顶点位置、法线、颜色、色彩指数、纹理坐标、多边形边缘标识的传输速度,引入了新的纹理特性等等。
    1997年,Windows 95下3D游戏的大量涌现,游戏开发公司迫切需要一个功能强大、兼容性好的3D图形接口,而当时微软公司自己的3D图形接口DirectX 3.0功能却是很糟糕。因而以制作《雷神之锤》等经典3D射击游戏而著名的id公司同其它一些游戏开发公司一同强烈要求微软在Windows 95中加入对OpenGL的支持。微软公司最终在Windows 95的OSR2版和后来的Windows 版本中加入了对OpenGL的支持。这样,不但许多支持OpenGL的电脑3D游戏得到广泛应用,而且许多在3D图形设计软件也可以运用支持OpenGL标准的3D加速卡,大大提高其3D图形的处理速度。
    2003年的7月28日,SGI和ARB公布了OpenGL 1.5。OpenGL 1.5中包括OpenGL ARB的正式扩展规格绘制语言“OpenGL Shading Language”。OpenGL 1.5的新功包括:顶点Buffer Object、Shadow功能、隐蔽查询、非乘方纹理等。
    2004年8月,OpenGL2.0版本发布~OpenGL 2.0标准的主要制订者并非原来的SGI,而是逐渐在ARB中占据主动地位的3Dlabs。OpenGL2.0支持OpenGL Shading Language、新的shader扩展特性以及其他多项增强特性。
    2008年8月初Khronos工作组在Siggraph 2008大会上宣布了OpenGL 3.0图形接口规范,GLSL1.30 shader语言和其他新增功能将再次对未来开放3D接口发展指明方向。
    OpenGL 3.0 API开发代号为Longs Peak,和以往一样,OpenGL 3.0仍然作为一个开放性和跨平台的3D图形接口标准,在Shader语言盛行的今天,OGL3.0增加了新版本的shader语言:GLSL 1.30,可以充分发挥当前可编程图形硬件的潜能。同时,OGL3.0还引入了一些新的功能,例如顶点矩阵对象,全帧缓存对象功能,32bit浮点纹理和渲染缓存,基于阻塞队列的条件渲染,紧凑行半浮点顶点和像素数据,四个新压缩机制等等。
    2009年3月又公布了升级版新规范OpenGL 3.1,也是这套跨平台免费API有史以来的第九次更新。OpenGL 3.1将此前引入的OpenGL着色语言“GLSL”从1.30版升级到了1.40版,通过改进程序增强了对最新可编程图形硬件的访问,还有更高效的顶点处理、扩展的纹理功能、更弹性的缓冲管理等等。宽泛地讲,OpenGL 3.1在3.0版的基础上对整个API模型体系进行了简化,可大幅提高软件开发效率。
    2009年8月Khronos小组发布了OpenGL 3.2,这是一年以来OpenGL进行的第三次重要升级。该版本仍然延续了OpenGL发展的方向让图形程序开发者能在多种操作系统和平台下更好的利用新的GPU功能。OpenGL3.2版本提升了性能表现、改进了视觉质量、提高了几何图形处理速度,而且使Direct3D程序更容易移植为OpenGL。除OpenGL之外,Khronos还将其开发的其它标准进行了协调改进,以求可以在更广泛的领域提供强大的图形功能和计算生态系统,这些标准包括用于并行计算的OpenCL、用于移动3D图形开发的OpenGL ES和用于网络3D开发的WebGL。
    2010年7月26日发布OpenGL 4.1和OpenGL OpenGL Shading Language 4.10。OpenGL4.1提高视觉密集型应用OpenCL™的互操作性,并继续加速计算剖面为核心的支持和兼容性第一次推出的OpenGL 3.2,使开发人员能够使用一个简化的API或保留向后兼容现有的OpenGL代码,这取决于他们的市场需求。
    Khronos旗下的OpenGL ARB(Architecture Review Board)工作组推出了GLSL 1.5OpenGLShading Language(OpenGL着色语言)的升级版,以及在OpenGL3.2框架下推出了两个新功能,可以让开发者在开发新程序时能够在使用流水线内核特性或兼容性特性之间做出选择,其中兼容性特性会提供与旧版OpenGL之间的兼容性。
    2011年8月9日在温哥华举行的SIGGRAPH 2011大会上Khronos发布了新的OpenGL 4.2标准细节,对于支持现有硬件的API加入了部分新的支持特性。和OpenGL 4.1一样,OpenGL 4.2主要应用于DX11级别硬件如NVIDIA GeForce 400/500,Radeon HD 5000/6000系列显卡,不过NVIDIA的开发者社区之前曾经表示部分特性可通过扩展功能在最老支持OpenGL2/DX9级别的硬件上实现。

    特点功能

    OpenGL是一个开放的三维图形软件包,它独立于窗口系统和操作系统,以它为基础开发的应用程序可以十分方便地在各种平台间移植;OpenGL可以与Visual C++紧密接口,便于实现机械手的有关计算和图形算法,可保证算法的正确性和可靠性;OpenGL使用简便,效率高。它具有七大功能:
    1.建模:OpenGL图形库除了提供基本的点、线、多边形的绘制函数外,还提供了复杂的三维物体(球、锥、多面体、茶壶等)以及复杂曲线和曲面绘制函数。
    2.变换:OpenGL图形库的变换包括基本变换和投影变换。基本变换有平移、旋转缩放镜像四种变换,投影变换有平行投影(又称正射投影)和透视投 影两种变换。其变换方法有利于减少算法的运行时间,提高三维图形的显示速度。
    3.颜色模式设置:OpenGL颜色模式有两种,即RGBA模式和颜色索引(Color Index)。
    4.光照和材质设置:OpenGL光有自发光(Emitted Light)、环境光(Ambient Light)、漫反射光(Diffuse Light)和高光(Specular Light)。材质是用光反射率来表示。场景(Scene)中物体最终反映到人眼的颜色是光的红绿蓝分量与材质红绿蓝分量的反射率相乘后形成的颜色。
    5:纹理映射(Texture Mapping)。利用OpenGL纹理映射功能可以十分逼真地表达物体表面细节。
    6:位图显示和图象增强图象功能除了基本的拷贝和像素读写外,还提供融合(Blending)、抗锯齿(反走样)(Antialiasing)和雾(fog)的特殊图象效果处理。以上三条可使被仿真物更具真实感,增强图形显示的效果。
    7:双缓存动画(Double Buffering)双缓存即前台缓存和后台缓存,简言之,后台缓存计算场景、生成画面,前台缓存显示后台缓存已画好的画面。
    此外,利用OpenGL还能实现深度暗示(Depth Cue)、运动模糊(Motion Blur)等特殊效果。从而实现了消隐算法。OpenGL设备运用,目前瑞芯微2918芯片和英伟达芯片Tegra2 就是采用OpenGL 2.0技术进行图形处理,而基于瑞芯微2918芯片方案代表是台电T760和微蜂X7平板电脑所采用到。

    高级功能

    OpenGL被设计为只有输出的,所以它只提供渲染功能。核心API没有窗口系统、音频、打印、键盘/鼠标或其它输入设备的概念。虽然这一开始看起来像是一种限制,但它允许进行渲染的代码完全独立于他运行的操作系统,允许跨平台开发。然而,有些整合于原生窗口系统的东西需要允许和宿主系统交互。这通过下列附加API实现:
    * GLX - X11(包括透明的网络)
    * WGL - Microsoft Windows
    * AGL - Apple MacOS
    另外,GLUT库能够以可移植的方式提供基本的窗口功能。

    规范发布

    2012年8月7日,Khronos Group组织也公布了桌面版OpenGL的最新版本4.3,也算是给这个3D API二十岁生日的最好礼物。 1992年,OpenGL 1.0诞生,此后历经二十年发展,先后衍生了四个世代,功能日渐强大,普及范围也是越来越广。虽然它没有微软DirectX在游戏中那么风光,但也在专业图形等领域成为众多开发者的首选,而且陆续衍生了OpenGL ES、OpenCL、WebGL等一帮同门师兄弟,生态系统日臻完善。

    发展现状

    编辑
    OpenGL仍然是唯一能够取代微软对3D图形技术的完全控制的API。它仍然具有一定的生命力,但是Silicon Graphics已经不再以任何让微软不悦的方式推广OpenGL,因而它存在较高的风险。游戏开发人员是一个有着独立思想的群体,很多重要的开发人员目前仍然在使用OpenGL。因此,硬件开发商正在设法加强对它的支持。Direct3D目前还不能支持高端的图形设备和专业应用; OpenGL在这些领域占据着统治地位。最后,开放源码社区(尤其是Mesa项目)一直致力于为任何类型的计算机(无论它们是否使用微软的操作系统)提供OpenGL支持。
    目前,国外的三维游戏开发技术,从创意、策划、研究开发与实现,到游戏的运营与维护,都有大量的知识值得学习和摸索。由于 Linux 操作系统平台的大力推广,基于Linux 的各种应用软件也不断壮大,因此基于跨平台图形库的跨平台三维游戏开发也越来越受重视。OpenGL(open graphics library)是一种独立的平台无关的三维图形开发库,在各种语言下进行主框架开发并结合应用OpenGL 函数都可以开发出三维游戏。但是由于框架开发的平台相关性使游戏无法跨平台编译运行,因此glut+OpenGL 的方式成了一种很好的选择。但是在对复杂框架和各种媒体的支持方面,glut 并不理想。在Linux 下可以采用FLTK 等框架平台技术实现包括按钮在内的比较复杂的框架功能,但是需要专门的Linux 开发环境,众多的Window 环境下的KDE 爱好者明显对此无法适从。相反,SDL(Simple DirectMedia Layer)作为免费的跨平台多媒体应用编程接口,已经被人们广泛用于开发二维游戏,其优秀的消息框架支持、文件支持和声音支持等都使得它成为能与微软DirectX 匹敌的最为成熟的技术之一。
    截止2012年8月7日,Khronos Group公布了最新的OpenGL 4.3规范。

    有关技术

    编辑

    扩展

    当独立厂商创建一种新技术时,OpenGL标准允许它们通过“扩展”的方法提供所扩展的功能。然后一个扩展就分成两部分发布:包含扩展函数原型的头文件和作为厂商的设备驱动。每个厂商有一个用于命名它们的新函数和常量的字母缩写。例如,NVIDIA的缩写(“NV”)用于定义它们的专有函数“glCombinerPara-
    meterfvNV()”和它们的常量“GL_NORMAL_MAP_NV”。如果多于一个厂商同意实现相同的扩展功能,那么就用缩写“EXT”。进一步,架构评审委员会可能“祝福”这个扩展,那么这就被称为一个“标准扩展”,使用缩写“ARB”。第一个ARB扩展是GL_ARB_multitexture。根据官方扩展提升路径,多纹理不再是可选实现的ARB扩展,它已经是OpenGL 1.4以后的核心API的一部分。
    几个库创建在OpenGL之上,提供了OpenGL本身没有的功能:
    1)GLU
    2)GLUT
    3)GLUI
    4)GLEW
    5)GLEE[1] 
    6)FREEGLUT(GLUT已经于1998年不再更新了。于是就有了freeglut)
    特别是,OpenGL Performer库——由SGI开发并可以在IRIXLinuxMicrosoft Windows的一些版本上使用,构建于OpenGL,可以创建实时可视化仿真程序。
    当开发者需要使用最新的OpenGL扩展时,他们往往需要使用GLEW或者是GLEE库提供的功能,可以在程序的运行期判断当前硬件是否支持相关的扩展,防止程序崩溃甚至造成硬件损坏。

    绑定

    为了加强它的多语言和多平台特性,已经用很多语言开发了OpenGL的各种绑定和移植。最值得注意的是,Java3D库已经可以利用OpenGL(另一个选择可能是DirectX)作为它的硬件加速了。OpenGL官方网页列出了用于Java、Fortran90、Perl、Pike、PythonAdaVisual Basic的多个绑定。

    规范

    Khronos Group在2009年3月又公布了升级版新规范OpenGL 3.1,也是这套跨平台免费API有史以来的第九次更新。
    OpenGL 3.1将此前引入的OpenGL着色语言“GLSL”从1.30版升级到了1.40版,通过改进程序增强了对最新可编程图形硬件的访问,还有更高效的顶点处理、扩展的纹理功能、更弹性的缓冲管理等等。宽泛地讲,OpenGL 3.1在3.0版的基础上对整个API模型体系进行了简化,可大幅提高软件开发效率。
    OpenGL 3.1主要新特性:Texture Buffer Objects(纹理缓冲对象)、Uniform Buffer Objects(统一缓冲对象)、Signed Normalized Textures(符号正常化纹理)、Primitive Restart(基本元素重启)、Instancing(实例化)、CopyBuffer API(拷贝缓冲接口)……
    与OpenGL 3.1规范同步,OpenGL架构评审委员会(ARB)也发布了一个兼容性扩展,能让开发人员在访问OpenGL 3.1里已经删除的OpenGL 1.x/2.x功能,确保应用程序的全面向下兼容性。
    OpenGL 3.1公布后,业界图形厂商很快予以了大力支持。AMD OpenGL主管Suki Samra表示:“AMD全面用户OpenGL API,会在今后的Radeon和FirePro产品驱动程序中支持OpenGL 3.1。”NVIDIA市场营销副总裁Dan Vivoli表示:“NVIDIA承诺尽快部署OpenGL 3.1,我们也很自豪地在规范公布同一天放出了自己的测试版驱动程序。”
    市场调研机构Jon Peddie Research预测,OpenGL 3.1规范图形硬件的安装规模将超过1亿。AMD、NVIDIA、S3 Graphics的显卡驱动都已经支持OpenGL 3.0。

    相关信息

    编辑
    1995年至1996年,微软实行了一项新计划,以支持在Windows95上运行游戏,目标是把市场扩展到被任天堂和世嘉控制的游戏领域。然而,微软不想用已经在NT上提供的OpenGL技术。微软收购了Rendermorphics,Ltd.并得到他的被称作RealityLab的3D API。经重新整理,微软发布了新的3D API——Direct3D
    微软,推行Direct3D,冻结OpenGL!
    微软当时拒绝了在Window95上支持OpenGL。不止如此,微软采取异常手段收回对OpenGL的MCD驱动接口的支持,以致硬件厂商不得不放弃已经进入最后测试的OpenGL驱动。微软的市场部门开始向游戏开发商、硬件厂商、新闻出版机构推销Direct3D,同时排斥OpenGL。
    API之战!
    Silicon Graphics和很多OpenGL用户都依赖OpenGL创新且高性能的技术。但很明显微软打算用Direct3D代替OpenGL,尽管D3D有很多问题而且不能像OpenGL那样被硬件厂商扩展。Silicon Graphics决定在1996 SIGGRAPH会议上作一项演示。演示证明OpenGL至少和D3D一样快,从而驳倒微软的市场论调。因为OpenGL是业界公认标准,比D3D功能丰富,而且图像质量要高一些,所以演示在计算机图形和游戏开发社区导致了激烈论战。
    游戏开发者要求OpenGL和D3D站在同等地位!
    当技术和市场问题暴露,强烈的支持OpenGL行动开始了。Doom的开发者John Carmack声明拒绝D3D,Chris Hecker在游戏开发杂志上发表了两套API的全面分析,以微软应放弃D3D为结论。游戏开发者先后两次向微软递交请愿书。第一次由56名首席游戏开发者要求微软发行OpenGL MCD驱动,但未成功,因为会让OpenGL与D3D竞争。第二次的公开信由254人签名开始,截止时达到1400人。微软的回答仍是重申旧市场立场。尽管请愿者清楚的要求两套API同等竞争以促进发展,微软却以增加D3D的投资、更加减少OpenGL的投资为回应。
    Fahrenheit——D3D与OpenGL的合并?
    Silicon Graphics,Microsoft, HP,Intel达成协议联合开发下一代3D API——Fahrenheit。但不了了之,因为微软的打算是把OpenGL的技术用到D3D里并且以此之名驱除OpenGL的威胁。(估计DirectX 8 Graphics即是剩下微软独自开发的Fahrenheit,吸收了OpenGL的很多东西。)
    OpenGL豪气不减当年!
    OpenGL依然是唯一能与微软单独控制的D3D对立的API,尽管Silicon Graphics不再以任何微软不能接受的方式推行OpenGL。游戏开发这是独立的,并且很多关键人物在用OpenGL,因此,硬件厂商正努力提高对其支持。D3D仍不能支持高端图像和专业应用,而OpenGL主宰着这些土地。在开放原码社区,Mesa项目正提供独立于微软的OpenGL驱动。
    译者注:表面上好像D3D比OpenGL支持更多的功能,其实由于D3D不支持硬件扩展,如硬件全景阴影,硬件渲染顺序无关半透明材质等新技术根本无法使用,而D3D(特指D3D8)本身提供的功能只有一小部分能在使用HAL且硬件不支持时模拟,你要用大量代码分析硬件能力和采取不同策略。

    展开全文
  • OPENGL

    千次阅读 2010-10-29 20:00:00
    OPENGL常见问题汇总报告
    问:OpenGL中的Stencil Buffer是什么东西?
    答:模板缓存(Stencil Buffer)。它可以保持屏幕上某些部位的图形不变,而其它部位仍然可以进行图形绘制。比方说,可以通过模板缓存来绘制透过汽车挡风玻璃观看车外景物的 画面。首先,将挡风玻璃的形状存贮到模板缓存中去,然后再绘制整个场景。这样,模板缓存挡住了通过挡风玻璃看不见的任何东西,而车内的仪表及其它物品只需 绘制一次。因此,随着汽车的移动,只有外面的场景在不断地更改。
    
    
    问:glos.h是什么文件?
    答:判别操作系统的头文件。
    
    问:OpenGL的左右缓冲区如何使用?即:gldrawbuffer()中的,GL_RIGHT、GL_LEFT参数的使用。我想做一副立体图,(两副图像交替在屏幕上不停刷新)。 图形加速卡选用的是华硕的3800带立体镜的那一种。
    答:这需要看驱动程序是否支持OpenGL的左右缓冲区。据我们所知,华硕显卡不带这样的驱动。而象Diamond Fire GL系列、ELSA的Glorial系列等显卡支持这种功能。在购买显卡时,应认清驱动程序的支持性能。
    
    问:请问用在OpenGL编程中有哪些方法可以得到两个曲面的交线?
    答:OpenGL用于绘制图形,没有交线计算,需要自行开发算法。
    
    问:关于OpenGL中雾的问题。
    答: 首先我想说一下OpenGL中雾的定义,OpenGL中雾的模式有三种:GL_LINEAR,GL_EXP,GL_EXP2。以GL_LINEA为例:雾 的混合因子f(0=<=1)的计算公式为f=(end-z)/(end-start) 。其中start 和end 为程序设置的雾的起点和终点(即glFogf(GL_FOG_START,start); glFogf(GL_FOG_END,end);)。最值得关注的是z的定义。我手头上有好几本OpenGL的参考书,但介绍了雾的定义的却只有两本。在 《OpenGL编程实例与技巧》(吴斌 毕丽蕴 编著)中,他们认为“z表示视点与图元中心的观察坐标之间的距离”。在《OpenGL深入编程与实例揭秘》(彭晓明 王坚 编著)中,他们认为“z是像素或顶点在眼坐标系中的z坐标分量值(总为负值)”。在VC++的联机帮助中说的是“Let z be the distance in eye coordinates from the origin to the fragment being fogged. ”。如果所绘制的物体不大(比如长和宽都为1个单位的矩形),那么上面所说的都可以近似为:z就是视点与物体在观察坐标之间的距离(负值)。当绘制的物体 很大时(比如长和宽都为200个单位的矩形),我认为上面的说法都值得探讨。我认为z可能是“视点与绘制物体边缘在观察坐标之间的最近距离(负值)”,上 次我绘制图形时绘制了几个很大的物体,所以当我移动物体时,雾的效果并不是近处清晰,远处模糊。我想如果把大的物体划分为很小的物体进行绘制,就可以解决 问题。
    
    问:请问画树时如何将树设置为透明格式?
    答:可以使用融合的方法。
    
    问:我在做一个虚拟场景时是用Bezier曲面拟合环境中的曲面,然后再贴以纹理,但我发现这样极其占用系统资源,而且我用了显示列表来处理。我想请教一下有没有什么别的方法来拟合曲面而不是那么占用系统资源,或者是我的用法不对。
    答:当然不能用Bezier曲面拟合环境中的曲面,Bezier曲面需要大量的计算。最好的办法是直接获得曲面的顶点,采用TRANGLES或四边形来绘制。
    
    问: 我已经做好了一个视景,现在要做它的后视景,但是有个问题就是后视景并不能由前视景简单的经过旋转180度得到(因为后视的原理是以镜平面对称),例如现 在将视景绕Y轴(视景坐标系)旋转180度,出来的效果是左边的物体到右边而右边的物体到左边了,所以也不符合,现在想请教一下有没有比较简便些的算法来 实现这个后视景问题。
    答:这个问题不只是旋转坐标轴,而是镜面反射编程,你可网上有关编程示例。
    
    问:我用OpenGL画曲面,原始数据通过打开数据文件获取,但为什么打开一个数据文件画好后,紧接着打开另一个文件再画时,其形状和颜色都受第一次的曲面影响?为什么我的曲面重画(刷新视区)后变成了坐标系中的平面?即各点Z坐标的值表面上看似乎变的相等了?
    答:显然你没有重新设置颜色。至于形状,检查坐标数组。检查Z轴坐标值。另外,注意几何变换PushMatrix和PopMatrix。
    
    问:如何通过屏幕坐标获取物体三维坐标?
    
    
    答:使用gluUnProject函数。
    
    问:如何在OpenGL中将显示列表的文本用字体对话框控制?
    答:在显示列表中就不能进行中间变化!用字体对话框控制字体,只能在显示列表之前。
    
    问:导入3D模型文件为什么总是不能很好的倒入纹理贴图,有什么办法可以很好的导入一个完整的3D模型文件?
    答:这种情况一般都是由于纹理坐标错误。读带纹理3DS格式模型一般比较复杂,需要时间理解透彻才行,暂时可以用材质(不含纹理)代替。借鉴网上一些免费纹理模型贴图的示例也行呀。
    
    问:我的工程将视区分为两个后(加了一个FormView窗体,用于放一些控制图形缩放的控件,这样它于绘图窗口共享原来的视区)为什么用OpenGL画的图不见了?我需要注意什么?错在那里?
    答:注意设置好象素格式。
    
    问: 我自己绘的四边形片怎么原来有边框和界限即一个个的小方格,现在运行程序后突然变成了一条没有任何界限的色带?程序片段如下:
    glPolygonMode(GL_FRONT,GL_FILL); 111
    glBegin(GL_QUAD_STRIP);
    for(i=0;i<=HEIGHTNUMBER;i++)
    {
    glVertex3f(base,Ybase- i*Yalphe,0.0);
    glColor3f(m_getMinR+i*Redalphe,
    m_getMinG+i*Greenalphe,m_getMinB+i*Bluealphe);
    }
    glEnd();
    答:调用了glPolygonMode的填充方式,当然变成色带。
    
    问:用OpenGL做人体动画合适吗?
    答:做动画可用3DSMAX这样的动画软件。而实时开发则需要OpenGL。OpenGL是很好的三维图形库,当然做人体动画需要比较复杂的编程。
    
    问:OpenGL Extension是什么?
    答:Extension 是OpenGL的扩展库,各硬件厂家为了更好地发挥自己的芯片的图形性能,驱动程序支持许多特别有用的扩展库。当然,SGI和微软力求统一标准,无奈象 TNT2这样的芯片产量太大,所以厂家完全可以自行其是。为此,扩展库的支持种类、支持程度与计算机中的图形卡及其驱动程序有关。象SGI NT工作站完全支持SGI发布的所有扩展库,nVIDIA TNT2图形芯片一般都支持nVIDIA的扩展库。所支持的扩展库名称可在驱动程序显示高级设置中看到。目前ELSA这样的图形卡的性能较为优越,其 nVIDIA GeForce2为芯片的图形卡所支持的扩展库相对比较完整。
    
    问:在OpenGL中,房间漫游时总是要“穿墙而过”,下楼梯时总是悬浮在半空中。请教解决办法。
    答:这需要图形学中的“碰撞检测”方法,具体过程比较复杂并很有技巧性。自己到网上看看吧。
    
    问:请问在OpenGL的辅助库函数中是否有可以将所绘图形存为位图的函数?我想把所绘图形存为位图格式,有哪些方法?
    答:没有现成的函数,自己写吧。
    
    问:在标准C语言下,可用glBingTexture来贴纹理(以便硬件加速),不知道在Visual C++ 6.0下为什么不行,还是我没考虑到某些什么?
    答:检查函数的使用方法;正确安装OpenGL1.1,甚至OpenGL1.2。
    
    问:Delphi和Visual C++都支持OpenGL,如果要编类似模拟飞行的程序, 哪个更容易一些,或者说Delphi和Visual C++哪个处理图形动画更快一些?
    答:Delphi做界面比VC较容易,做算法较麻烦。但VC做算法和图形程序都会更好一些。
    
    问:在进行编程时,我想把自己的三维模型或人体骨骼运动输出到3DS中,不知我可找到相应答案吗?
    答:3DS MAX好象还不能直接接受外部运动数据,但它可以生成运动数据(使用一些插入件,网站里有),或者先有运动数据后,再设法输入到3DSMAX中。
    
    问:我们知道通过一个点的三维坐标可很方便地计算出在二维屏幕上该点的二维坐标(用OpenGL编程更容易)。但反过来,在知道二维显示坐标的前提下怎样计算出三维坐标解集(应为一直线)?
    答:这个问题可用OpenGL的gluUnproject()函数。
    
    问:在OpenGL编程中,我遇到一个问题:在知道三自由度转角与臂长的前提下如何计算臂长端点的空间坐标(x,y,z)。我用C语言进行了编程,不知OpenGL中是否有相应的函数?
    答:这个问题属计算问题,需要自行编程解决,OpenGL 主要解决三维图形及效果的绘制问题。
    
    
    
    问:请问如何解决大数据量的三维可视化的速度问题?除此之外还有没有别的办法?
    答:OpenGL只是一个很好绘图渲染的库,大数据量的算法则需要自行编程实现。
    
    问:我想做一个有关人体模型的三维重建的东西,该如何做呢?
    答:关于三维重建的问题,由于国内还处于学术研讨层次上,我建议首先看一些有关论文,再考虑程序实现。
    1)医学图象三维重建及可视化技术研究
    http://www.cad.zju.edu.cn/chinagraph/chinese/specialtopic/visulize/Visual_Hot_QinXuJia.ppt
    2)科学计算视化及虚拟现实医学应用
    http://www.cad.zju.edu.cn/chinagraph/chinese/specialtopic/visulize/VisualHOT3.ppt
    
    3)应用数学研究室
    研究室的主要研究方向有:工业CT图像重建的数学理论与算法。
    http://www.biti.edu.cn/t_r/yy.htm
    
    问:网上一些程序中用到的纹理图像并不是位图格式,而是以bw或rgb为扩展名的文件,不知用什么软件才能打开这些图形文件,并且我想问一下这些图形文件能否转换成位图格式?我用Acdsee和Photoshop都打不开。
    答:可以用Acdsee2.4版打开rgb格式图象文件,你也可直接在OpenGL程序中使用bmp文件,可查glu.h中的image宏。
    
    问:请问在OpenGL下如何画凹多边形,若分解为三角形,则不能使用glPolygonMode功能,有什么办法解决。
    答:一般都要预处理,保证不出现凹多边形,但OpenGL也提供了一种处理方法,即Tesselation分化方法,但占内存大,影响速度性能,不宜使用。
    
    问:如何解决由于Win系统不支持spong平滑模式 导致曲面镜面光不平滑的问题?
    答:需要材质、网格密度与SMOOTH绘制模式结合。
    
    问:如何锁定图形中部分图形对象,而只对某些对象进行操作?
    答:对每个对象命名(可用OpenGL中的显示列表方法),然后分别控制就可。
    
    问:有关OpenGL的颜色操作与纹理,材质和光照之间的关系。
    答:说来话长,需好好看书。
    
    问:在拾取操作过程中,整个显示列表是否不起作用?如果要对单个地物进行操作时,是否必须单个进行建立显示列表?
    答:显示列表与内存含义类似,一旦确定显示列表,其中的内容就不要改变;但可加速。
    
    问:请问如何在不修改其他图形对象时,删除某些对象?
    答:仍然用显示列表方法。
    
    问:我要将一个人的照片用贴纹理的方法贴到一视景中,要使除人以外的部分要是透明的,而位图往往是矩形的,那么在编程如何才能让除人以外的部分透明呢?
    答:可考虑使用stencil纹理贴图方法。
    
    问:如何锁定图形中部分图形对象,而只对某些对象进行操作?
    答:对每个对象命名(可用OpenGL中的显示列表方法),然后分别控制就可。
    
    问:我在OpenGL中用一维求值器绘制Bezier曲线:
    glBegin(GL_LINE_STRIP);
    for (i = 0; i <= 30; i++)
    glEvalCoord1f((GLfloat) i/30.0);
    glEnd();
    该Bezier曲线是由30段line构成,我需要在场景中设置一个物体沿该曲线路径移动, 我怎么获得各个顶点的坐标值呢?反馈信息好象只包含窗口可见的顶点信息,有更好的办法吗?请赐教。
    答: 最直接的办法是你自己来计算(只是简单的Matrix变换)当然也是比较麻烦的;另外可以让OpenGL帮你算,方法是定出物体的坐标系沿着Bezier 曲线移动后的新位置,这种移动可能不唯一(比如简单的平移或利用曲线的切平面和法平面来定义),所以你必须定出移动的规则,有了新的坐标系数据,可以gl 相应的Matrix,就可以直接显示了,如果要求出实际的坐标(如果只是想显示是没有必要计算的),用Matrix去乘吧。
    
    问:我现在遇到一个问题,就是用OpenGL来画出一个动态的海洋,波浪涌动。因为还要有船贴图似乎不行,而计算海平面的三维坐标值简直太麻烦了,巨量的点,复杂的法线...。最后一招,用3DS MAX画出来在加载进去,但格式转换也不容易。我该怎么做呢?
    答:这个问
    
     
    
    题其实可以用很简单的方法解决。可用一个简单的四边形或格网构成海面框架,然后进行海面纹理贴图,让纹理动起来,不就有动态波浪海洋的场景了吗。在海面上的船可以继续加,各种变换照常进行。
    
     
    
    
    问: 在用C++Builder编写OpenGL程序时,在Scene窗口中,用鼠标移动物体,能否有办法知道移动后物体所在的坐标位置?用鼠标任意旋转物体, 怎样知道该物体的旋转角度和方向等数值。即:物体初始位于原点,怎样把鼠标移动物体的视觉效应转化为精确的坐标变换?
    答:需要建立一个新的三维 坐标系,将视点、图像投影面(Scene窗口)以及物体等,一起定位与这个坐标系里。当鼠标移动时,延长视点与鼠标屏幕点的连线,使其相交与物体移动的面 (假定使用二维鼠标,物体在XY或YZ或ZX或球面上移动),其交点就是物体移动后的坐标点。旋转角度则根据前后两次位置不同,计算出相对于某个旋转中心 (如视点、物体中心点或坐标原点等)的旋转角度。
    
    问:MiniGL与OpenGL的内容有什么不同?
    答:MiniGL只是OpenGL的一个外包装,在它的内部是根据当前的显卡来决定实际的OpenGL驱动(如PowerVR、3dfx、etc..),MiniGL实际并不实现任何OpenGL功能。
    
    问:在编写OpenGL的纹理程序时,函数auxDIBImageLoad()打开文件时返回“文件打开错误”,我希望了解调入位图的详细方法。
    答:1)在调用该函数之前必须确认调入的图象是BMP格式,而且宽和高是2的n次幂。
    2)OpenGL中调入位图方法。OpenGL中调入位图作为纹理,关键是清楚位图文件的结构,对于Windows下的位图,一般从第54个字节处开始才是图形数据,下面是个例子:
    int MakeTexture128(char *name,GLubyte Image[128][128][3] )
    {
    GLint index;
    FILE *fp;
    int i, j, r,g,b;
    fp=fopen(name,"rb");
    if(fp==NULL)
    {
    fprintf(stderr, "Cannot open input file./n");
    }
    fseek(fp,54L,0);
    for (i = 0; i <128; i++)
    {
    for (j = 0; j < 128; j++)
    {
    r=fgetc(fp);
    g=fgetc(fp);
    b=fgetc(fp);
    Image[i][j][0] = (GLubyte) b;
    Image[i][j][1] = (GLubyte) g;
    Image[i][j][2] = (GLubyte) r;
    }
    }
    fclose(fp);
    index =glGenLists(1);
    glNewList(index,GL_COMPILE);
    glTexImage2D(GL_TEXTURE_2D,0,3,128,128,0,GL_RGB,GL_UNSIGNED_BYTE,&Image[0][0][0]);
    glEndList();
    return index;
    }
    
    问:在VC中创建OpenGL应用程序时,需要连接LIB目录中的opengl32.lib、glu32.lib、
    glaux.lib这三个函数库。但我不知道该如何将这三个文件同我的程序连接起来,特请教。
    答:可用二种方法:
    1)在VC的Project->Setting->Link->Object/Library modules中加入这三个库;
    2)在VC的Project->Add to Project->Files中加入这三个库。
    
    问:在OpenGL的一个完整的变换过程中,要经过一系统的矩阵变换,其中第一步是取景变换,或者叫视点变换。请问一个完整变换过程是否只能有一个视点?而这个视点的任何变换(取景变换)是否对于场景中所有模型均产生作用?
    答:对于一个视口(Viewport)而言只能有一个视点。视点的变换是否对场景中的模型起作用,还要看投影变换。
    
    
     
    展开全文
  • OpenGL

    千次下载 热门讨论 2007-10-31 17:08:37
    OpenGL开发库,包括如何在vc中利用
  • OpenGL安装包(全)

    千次下载 热门讨论 2010-07-20 21:25:07
    包括: GL.H GLAUX.H GLU.H glut.h GLAUX.LIB GLU32.LIB glut32.lib glut.lib OPENGL32.LIB glaux.dll glu32.dll glut32.dll glut.dll opengl32.dll
  • 写给 python 程序员的 OpenGL 教程

    万次阅读 多人点赞 2019-01-26 08:47:24
    OpenGL 是 Open Graphics Library 的简写,意为“开放式图形库”,是用于渲染 2D、3D 矢量图形的跨语言、跨平台的应用程序编程接口(API)。OpenGL 不是一个独立的平台,因此,它需要借助于一种编程语言才能被使用。...

    1 预备知识

    OpenGL 是 Open Graphics Library 的简写,意为“开放式图形库”,是用于渲染 2D、3D 矢量图形的跨语言、跨平台的应用程序编程接口(API)。OpenGL 不是一个独立的平台,因此,它需要借助于一种编程语言才能被使用。C / C++ / python / java 都可以很好支持 OpengGL,我当然习惯性选择 python 语言。

    如果读者是 python 程序员,并且了解 numpy,接下来的阅读应该不会有任何障碍;否则,我建议先花半小时学习一下 python 语言。关于 numpy,可以参考我的另一篇博文《数学建模三剑客MSN》。事实上,我觉得 python 语言近乎于自然语言,只要读者是程序员,即便不熟悉 python,读起来也不会有多大问题。

    另外,读者也不必担心数学问题。使用 OpenGL 不需要具备多么高深的数学水平,只要能辅导初中学生的数学作业,就足够用了。

    1.1 坐标系

    在 OpenGL 的世界里,有各式各样的坐标系。随着对 OpenGL 概念的理解,我们至少会接触到六种坐标系,而初始只需要了解其中的三个就足够用了(第一次阅读这段话的时候,只需要了解世界坐标系就可以了)。

    • 世界坐标系(World Coordinates)

      世界坐标系是右手坐标系,以屏幕中心为原点(0, 0, 0),且是始终不变的。 在这里插入图片描述

    • 视点坐标系(Eye or Camera Coordinates)

      视点坐标是以视点为原点,以视线的方向为Z+轴正方向的坐标系。OpenGL 管道会将世界坐标先变换到视点坐标,然后进行裁剪,只有在视线范围(视景体)之内的场景才会进入下一阶段的计算。

    • 屏幕坐标系(Window or Screen Coordinates)

      OpenGL 的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。值得一提的是,OpenGL 可以只使用设备的一部分进行绘制,这个部分称为视区或视口(viewport)。投影得到的是视区内的坐标(投影坐标),从投影坐标到设备坐标的计算过程就是设备变换了。

    1.2 投影

    三维场景中的物体最终都会显示在类似屏幕这样的二维观察平面上。将三维物体变为二维图形的变换成为投影变换。最常用的投影有两种:平行投影和透视投影。如下图所示,F 是投影面,p1p2 为三维空间中的一条直线,p’1 和 p’2 分别是 p1 和 p2 在 F 上的投影,虚线表示投影线,O 为投影中心。
    在这里插入图片描述

    • 平行投影
      这里所说的平行投影,特指正交平行投影——投影线垂直于投影面。将一个三维点 (x,y,z) 正交平行投影到 xoy 平面上,则投影点坐标为 (x,y,0)。由于平行投影丢弃了深度信息,所以无法产生真实感,但可以保持物体之间相对大小关系不变。

    • 透视投影
      透视投影将投影面置于观察点和投影对象之间,距离观察者越远的物体,投影尺寸越小,投影效果具有真实感,常用于游戏和仿真领域。

    1.3 视景体

    无论是平行投影还是透视投影,投影成像都是在投影面上——我们可以把投影面理解成显示屏幕。世界坐标系描述的三维空间是无限的,投影平面是无限的,但(我们能够看到的)屏幕面积总是有限的,因此在投影变换时,通常只处理能够显示在屏幕上的那一部分三维空间。从无限三维空间中裁切出来的可以显示在屏幕上的部分三维空间,我们称之为视景体。视景体有六个面,分别是左右上下和前后面。

    对于平行投影而言,视景体是一个矩形平行六面体;对于透视投影来说,视景体是一个棱台。理解这一点并不难:因为越远处的物体在投影窗口的透视投影越小,也就意味着填满投影窗口需要更大的体量,视景体自然就变成了棱台。
    在这里插入图片描述

    1.4 视口

    对于平行投影而言,视口就是由视景体的左右上下四个面围成的矩形,对于透视投影来说,视口就是视景体的前截面在投影窗口上的透视投影。

    视口是 OpenGL 中比较重要的概念,现阶段可以简单理解成屏幕(或其他输出设备)。事实上,视口和屏幕是相关但又不相同的,屏幕有固定的宽高比,而视口大小可以由用户自行定义。通常,为了适应不同宽高比的屏幕,在设置视口时,会根据屏幕宽高比调整视景体(增加宽度或高度)。

    1.5 视点

    现实生活中,人们看到的三维空间物体的样子取决于观察者站在什么角度去看。这里面包含着三个概念:

    • 观察者的位置:眼睛在哪儿?
    • 观察者的姿势:站立还是倒立?左侧卧还是右侧卧?
    • 观察对象:眼睛盯着哪里?

    对应在 OpenGL 中,也有同样的概念,即视点的位置、瞄准方向的参考点,以及(向上的)方向。

    1.6 OpenGL 变换

    下图是三维图形的显示流程。世界坐标系中的三维物体经过视点变换和一系列几何变换(平移、旋转、缩放)之后,坐标系变换为视点坐标系;经过投影和裁剪之后,坐标系变换为归一化设备坐标系;最后经过视口变换显示在屏幕上,相应地,坐标系变成了窗口坐标系。
    在这里插入图片描述

    • 视点变换:相当于设置视点的位置和方向
    • 模型变换:包括平移、旋转、缩放等三种类型
    • 裁剪变换:根据视景体定义的六个面(和附加裁剪面)对三维空间裁剪
    • 视口变换:将视景体内投影的物体显示在二维的视口平面上

    2 安装 pyopengl

    如果想当然地使用 pip 如下所示安装,可能会有一些麻烦。

    pip install pyopengl
    

    当我这样安装之后,运行 OpenGL 代码,得到了这样的错误信息:

    NullFunctionError: Attempt to call an undefined function glutInit, check for bool(glutInit) before calling
    

    原来,pip 默认安装的是32位版本的pyopengl,而我的操作系统是64位的。建议点击这里下载适合自己的版本,直接安装.whl文件。我是这样安装的:

    pip install PyOpenGL-3.1.3b2-cp37-cp37m-win_amd64.whl
    

    3 OpenGL 库及函数简介

    我第一次接触 OpenGL 的 GL / GLU / GLUT 的时候,一下就被这些长得像孪生兄弟的库名字给整懵圈了,要不是内心强大,也许就跟 OpenGL 说再见了。时间久了才发现,OpenGL 的库及函数命名规则非常合理,便于查找、记忆。

    OpenGL函数的命名格式如下:

    <库前缀><根命令><可选的参数个数><可选的参数类型>
    

    常见的库前缀有 gl、glu、glut、aux、wgl、glx、agl 等。库前缀表示该函数属于 OpenGL 哪一个开发库。从函数名后面中还可以看出需要多少个参数以及参数的类型。I 代表 int 型,f 代表 float 型,d 代表 double 型,u 代表无符号整型。例如 glColor3f() 表示了该函数属于gl库,参数是三个浮点数。

    OpenGL 函数库相关的 API 有核心库(gl)、实用库(glu)、实用工具库(glut)、辅助库(aux)、窗口库(glx、agl、wgl)和扩展函数库等。gl是核心,glu是对gl的部分封装。glut是为跨平台的OpenGL程序的工具包,比aux功能强大。glx、agl、wgl 是针对不同窗口系统的函数。扩展函数库是硬件厂商为实现硬件更新利用OpenGL的扩展机制开发的函数。本文仅对常用的四个库做简单介绍。

    3.1 OpenGL 核心库 GL

    核心库包含有115个函数,函数名的前缀为gl。这部分函数用于常规的、核心的图形处理。此函数由gl.dll来负责解释执行。由于许多函数可以接收不同数以下几类。据类型的参数,因此派生出来的函数原形多达300多个。核心库中的函数主要可以分为以下几类函数:

    • 绘制基本几何图元的函数:
      glBegain()、glEnd()、glNormal*()、glVertex*()

    • 矩阵操作、几何变换和投影变换的函数:
      如矩阵入栈函数glPushMatrix(),矩阵出栈函数glPopMatrix(),装载矩阵函数glLoadMatrix(),矩阵相乘函数glMultMatrix(),当前矩阵函数glMatrixMode()和矩阵标准化函数glLoadIdentity(),几何变换函数glTranslate*()、glRotate*()和glScale*(),投影变换函数glOrtho()、glFrustum()和视口变换函数glViewport()

    • 颜色、光照和材质的函数:
      如设置颜色模式函数glColor*()、glIndex*(),设置光照效果的函数glLight*() 、glLightModel*()和设置材质效果函数glMaterial()

    • 显示列表函数:
      主要有创建、结束、生成、删除和调用显示列表的函数glNewList()、glEndList()、glGenLists()、glCallList()和glDeleteLists()

    • 纹理映射函数:
      主要有一维纹理函数glTexImage1D()、二维纹理函数glTexImage2D()、设置纹理参数、纹理环境和纹理坐标的函数glTexParameter*()、glTexEnv*()和glTetCoord*()

    • 特殊效果函数:
      融合函数glBlendFunc()、反走样函数glHint()和雾化效果glFog*()

    • 光栅化、象素操作函数:
      如象素位置glRasterPos*()、线型宽度glLineWidth()、多边形绘制模式glPolygonMode(),读取象素glReadPixel()、复制象素glCopyPixel()

    • 选择与反馈函数:
      主要有渲染模式glRenderMode()、选择缓冲区glSelectBuffer()和反馈缓冲区glFeedbackBuffer()

    • 曲线与曲面的绘制函数:
      生成曲线或曲面的函数glMap*()、glMapGrid*(),求值器的函数glEvalCoord*() glEvalMesh*()

    • 状态设置与查询函数:
      glGet*()、glEnable()、glGetError()

    3.2 OpenGL 实用库 GLU

    包含有43个函数,函数名的前缀为glu。OpenGL提供了强大的但是为数不多的绘图命令,所有较复杂的绘图都必须从点、线、面开始。Glu 为了减轻繁重的编程工作,封装了OpenGL函数,Glu函数通过调用核心库的函数,为开发者提供相对简单的用法,实现一些较为复杂的操作。此函数由glu.dll来负责解释执行。OpenGL中的核心库和实用库可以在所有的OpenGL平台上运行。主要包括了以下几种:

    • 辅助纹理贴图函数:
      gluScaleImage() 、gluBuild1Dmipmaps()、gluBuild2Dmipmaps()

    • 坐标转换和投影变换函数:
      定义投影方式函数gluPerspective()、gluOrtho2D() 、gluLookAt(),拾取投影视景体函数gluPickMatrix(),投影矩阵计算gluProject()和gluUnProject()

    • 多边形镶嵌工具:
      gluNewTess()、gluDeleteTess()、gluTessCallback()、gluBeginPolygon()、gluTessVertex()、gluNextContour()、gluEndPolygon()

    • 二次曲面绘制工具:
      主要有绘制球面、锥面、柱面、圆环面gluNewQuadric()、gluSphere()、gluCylinder()、gluDisk()、gluPartialDisk()、gluDeleteQuadric()

    • 非均匀有理B样条绘制工具:
      主要用来定义和绘制Nurbs曲线和曲面,包括gluNewNurbsRenderer()、gluNurbsCurve()、gluBeginSurface()、gluEndSurface()、gluBeginCurve()、gluNurbsProperty()

    • 错误反馈工具:
      获取出错信息的字符串gluErrorString()

    3.3 OpenGL 工具库 GLUT

    包含大约30多个函数,函数名前缀为glut。glut是不依赖于窗口平台的OpenGL工具包,由Mark KLilgrad在SGI编写(现在在Nvidia),目的是隐藏不同窗口平台API的复杂度。函数以glut开头,它们作为aux库功能更强的替代品,提供更为复杂的绘制功能,此函数由glut.dll来负责解释执行。由于glut中的窗口管理函数是不依赖于运行环境的,因此OpenGL中的工具库可以在X-Window, Windows NT, OS/2等系统下运行,特别适合于开发不需要复杂界面的OpenGL示例程序。对于有经验的程序员来说,一般先用glut理顺3D图形代码,然后再集成为完整的应用程序。这部分函数主要包括:

    • 窗口操作函数:
      窗口初始化、窗口大小、窗口位置函数等 glutInit()、glutInitDisplayMode()、glutInitWindowSize()、glutInitWindowPosition()

    • 回调函数:
      响应刷新消息、键盘消息、鼠标消息、定时器函数 GlutDisplayFunc()、glutPostRedisplay()、glutReshapeFunc()、glutTimerFunc()、glutKeyboardFunc()、glutMouseFunc()

    • 创建复杂的三维物体:
      这些和aux库的函数功能相同

    • 菜单函数:
      创建添加菜单的函数 GlutCreateMenu()、glutSetMenu()、glutAddMenuEntry()、glutAddSubMenu() 和 glutAttachMenu()

    • 程序运行函数:
      glutMainLoop()

    3.4 Windows 专用库 WGL

    针对windows平台的扩展,包含有16个函数,函数名前缀为wgl。这部分函数主要用于连接OpenGL和Windows ,以弥补OpenGL在文本方面的不足。 Windows专用库只能用于Windows环境中。这类函数主要包括以下几类:

    • 绘图上下文相关函数:
      wglCreateContext()、wglDeleteContext()、wglGetCurrentContent()、wglGetCurrentDC()、wglDeleteContent()

    • 文字和文本处理函数:
      wglUseFontBitmaps()、wglUseFontOutlines()

    • 覆盖层、地层和主平面层处理函数:
      wglCopyContext()、wglCreateLayerPlane()、wglDescribeLayerPlane()、wglReakizeLayerPlatte()

    • 其他函数:
      wglShareLists()、wglGetProcAddress()

    4 开始 OpenGL 的奇幻之旅

    4.1 OpenGL 基本图形的绘制

    4.1.1 设置颜色

    设置颜色的函数有几十个,都是以 glColor 开头,后面跟着参数个数和参数类型。参数可以是 0 到 255 之间的无符号整数,也可以是 0 到 1 之间的浮点数。三个参数分别表示 RGB 分量,第四个参数表示透明度(其实叫不透明度更恰当)。以下最常用的两个设置颜色的方法:

    glColor3f(1.00.00.0)  # 设置当前颜色为红色
    glColor4f(0.01.01.01.0)  # 设置当前颜色为青色,不透明度
    glColor3ub(0, 0, 255)  # 设置当前颜色为蓝色
    

    glColor 也支持将三个或四个参数以向量方式传递,例如:

    glColor3fv([0.01.00.0])  # 设置当前颜色为绿色
    

    特别提示:OpenGL 是使用状态机模式,颜色是一个状态变量,设置颜色就是改变这个状态变量并一直生效,直到再次调用设置颜色的函数。除了颜色,OpenGL 还有很多的状态变量或模式。在任何时间,都可以查询每个状态变量的当前值,还可以用 glPushAttrib() 或 glPushClientAttrib() 把状态变量的集合保存起来,必要的时候,再用 glPopAttrib() 或 glPopClientAttrib() 恢复状态变量。

    4.1.2 设置顶点

    顶点(vertex)是 OpengGL 中非常重要的概念,描述线段、多边形都离不开顶点。和设置颜色类似,设置顶点的函数也有几十个,都是以 glVertex 开头,后面跟着参数个数和参数类型,同样也支持将多个以向量方式传递。 两个参数的话,分别表示 xy 坐标,三个参数则分别表示 xyz 坐标。如有第四个参数,则表示该点的齐次坐标 w;否则,默认 w=1。至于什么是齐次坐标,显然超出了初中数学的范畴,在此不做探讨。

    glVertex2f(1.00.5) # xoy平面上的点,z=0
    glVertex3f(0.51.00.0) # 三维空间中的点
    

    4.1.3 绘制基本图形

    仅仅设置颜色和顶点,并不能画出来什么。我们可以在任何时候改变颜色,但所有的顶点设置,都必须包含在 glBegin() 和 glEnd() 之间,而 glBegin() 的参数则指定了将这些顶点画成什么。以下是 glBegin() 可能的参数选项:

    参数 说明
    GL_POINTS 绘制一个或多个顶点
    GL_LINES 绘制线段
    GL_LINE_STRIP 绘制连续线段
    GL_LINE_LOOP 绘制闭合的线段
    GL_POLYGON 绘制多边形
    GL_TRIANGLES 绘制一个或多个三角形
    GL_TRIANGLE_STRIP 绘制连续三角形
    GL_TRIANGLE_FAN 绘制多个三角形组成的扇形
    GL_QUADS 绘制一个或多个四边形
    GL_QUAD_STRIP 绘制连续四边形

    4.2 第一个 OpenGL 程序

    通常,我们使用工具库(GLUT)创建 OpenGL 应用程序。为啥不用 GL 或者 GLU 库呢?画画之前总得先有一块画布吧,不能直接拿起画笔就开画。前文说过,工具库主要提供窗口相关的函数,有了窗口,就相当于有了画布,而核心库和实用库,就好比各式各样的画笔、颜料。使用工具库(GLUT)创建 OpenGL 应用程序只需要四步(当然,前提是你需要先准备好绘图函数,并给它取一个合适的名字):

    1. 初始化glut库
    2. 创建glut窗口
    3. 注册绘图的回调函数
    4. 进入glut主循环

    OK,铺垫了这么多之后,我们终于开始第一个 OpenGL 应用程序了:绘制三维空间的世界坐标系,在坐标原点的后方(z轴的负半区)画一个三角形。代码如下:

    # -*- coding: utf-8 -*-
    
    # -------------------------------------------
    # quidam_01.py 三维空间的世界坐标系和三角形
    # -------------------------------------------
    
    from OpenGL.GL import *
    from OpenGL.GLUT import *
    
    def draw():
        # ---------------------------------------------------------------
        glBegin(GL_LINES)                    # 开始绘制线段(世界坐标系)
        
        # 以红色绘制x轴
        glColor4f(1.0, 0.0, 0.0, 1.0)        # 设置当前颜色为红色不透明
        glVertex3f(-0.8, 0.0, 0.0)           # 设置x轴顶点(x轴负方向)
        glVertex3f(0.8, 0.0, 0.0)            # 设置x轴顶点(x轴正方向)
        
        # 以绿色绘制y轴
        glColor4f(0.0, 1.0, 0.0, 1.0)        # 设置当前颜色为绿色不透明
        glVertex3f(0.0, -0.8, 0.0)           # 设置y轴顶点(y轴负方向)
        glVertex3f(0.0, 0.8, 0.0)            # 设置y轴顶点(y轴正方向)
        
        # 以蓝色绘制z轴
        glColor4f(0.0, 0.0, 1.0, 1.0)        # 设置当前颜色为蓝色不透明
        glVertex3f(0.0, 0.0, -0.8)           # 设置z轴顶点(z轴负方向)
        glVertex3f(0.0, 0.0, 0.8)            # 设置z轴顶点(z轴正方向)
        
        glEnd()                              # 结束绘制线段
        
        # ---------------------------------------------------------------
        glBegin(GL_TRIANGLES)                # 开始绘制三角形(z轴负半区)
        
        glColor4f(1.0, 0.0, 0.0, 1.0)        # 设置当前颜色为红色不透明
        glVertex3f(-0.5, -0.366, -0.5)       # 设置三角形顶点
        glColor4f(0.0, 1.0, 0.0, 1.0)        # 设置当前颜色为绿色不透明
        glVertex3f(0.5, -0.366, -0.5)        # 设置三角形顶点
        glColor4f(0.0, 0.0, 1.0, 1.0)        # 设置当前颜色为蓝色不透明
        glVertex3f(0.0, 0.5, -0.5)           # 设置三角形顶点
        
        glEnd()                              # 结束绘制三角形
        
        # ---------------------------------------------------------------
        glFlush()                            # 清空缓冲区,将指令送往硬件立即执行
    
    if __name__ == "__main__":
        glutInit()                           # 1. 初始化glut库
        glutCreateWindow('Quidam Of OpenGL') # 2. 创建glut窗口
        glutDisplayFunc(draw)                # 3. 注册回调函数draw()
        glutMainLoop()                       # 4. 进入glut主循环
    

    运行代码,我这里显示结果如下面左图所示。如果尝试运行这段代码出错的话,我猜应该是 pyopengl 安装出现了问题,建议返回到前面重读 pyopengl 的安装。
    在这里插入图片描述
    短暂的激动之后,你可能会尝试画一些其他的线段,变换颜色或者透明度,甚至绘制多边形。很快你会发现,我们的第一个程序有很多问题,比如:

    1. 窗口的标题不能使用中文,否则会显示乱码
    2. 窗口的初始大小和位置无法改变
    3. 改变窗口的宽高比,三角形宽高比也会改变(如上面右图所示)
    4. 三角形不应该遮挡坐标轴
    5. 改变颜色的透明度无效
    6. 不能缩放旋转

    没关系,除了第1个问题我不知道怎么解决(貌似无解),其他问题都不是事儿。和我们的代码相比,一个真正实用的 OpenGL 程序,还有许多工作要做:

    • 设置初始显示模式
    • 初始化画布
    • 绘图函数里面需要增加:
      1. 清除屏幕及深度缓存
      2. 投影设置
      3. 模型试图设置
    • 绑定鼠标键盘的事件函数

    4.3 设置初始显示模式

    初始化 glut 库的时候,我们一般都要用 glutInitDisplayMode() 来设置初始的显示模式,它的参数可以是下表中参数的组合。

    参数 说明
    GLUT_RGB 指定RGB颜色模式的窗口
    GLUT_RGBA 指定RGBA 颜色模式的窗口
    GLUT_INDEX 指定颜色索引模式的窗口
    GLUT_SINGLE 指定单缓存窗口
    GLUT_DOUBLE 指定双缓存窗口
    GLUT_ACCUM 窗口使用累加缓存
    GLUT_ALPHA 窗口的颜色分量包含 alpha 值
    GLUT_DEPTH 窗口使用深度缓存
    GLUT_STENCIL 窗口使用模板缓存
    GLUT_MULTISAMPLE 指定支持多样本功能的窗口
    GLUT_STEREO 指定立体窗口
    GLUT_LUMINANCE 窗口使用亮度颜色模型

    使用双缓存窗口,可以避免重绘时产生抖动的感觉。我一般选择 GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH 作为参数来设置初始的显示模式。

    4.4 初始化画布

    开始绘图之前,需要对画布做一些初始化工作,这些工作只需要做一次。比如:

    glClearColor(0.0, 0.0, 0.0, 1.0) # 设置画布背景色。注意:这里必须是4个参数
    glEnable(GL_DEPTH_TEST)          # 开启深度测试,实现遮挡关系
    glDepthFunc(GL_LEQUAL)           # 设置深度测试函数(GL_LEQUAL只是选项之一)
    

    如有必要,还可以开启失真校正(反走样)、开启表面剔除等。

    4.5 清除屏幕及深度缓存

    每次重绘之前,需要先清除屏幕及深度缓存。这项操作一般放在绘图函数的开头。

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 
    

    4.5 设置投影

    投影设置也是每次重绘都需要的步骤之一。glOrtho() 用来设置平行投影,glFrustum() 用来设置透视投影。这两个函数的参数相同,都是视景体的 left / right / bottom / top / near / far 六个面。

    视景体的 left / right / bottom / top 四个面围成的矩形,就是视口。near 就是投影面,其值是投影面距离视点的距离,far 是视景体的后截面,其值是后截面距离视点的距离。far 和 near 的差值,就是视景体的深度。视点和视景体的相对位置关系是固定的,视点移动时,视景体也随之移动。

    我个人认为,视景体是 OpengGL 最重要、最核心的概念,它和视口、视点、投影面、缩放、漫游等概念密切关联。只有正确理解了视景体,才能正确设置它的六个参数,才能呈现出我们期望的效果。

    为了在窗口宽高比改变时,绘制的对象仍然保持固定的宽高比,一般在做投影变换时,需要根据窗口的宽高比适当调整视景体的 left / right 或者 bottom / top 参数。

    假设 view 是视景体,width 和 height 是窗口的宽度和高度,在投影变换之前,需要先声明是对投影矩阵的操作,并将投影矩阵单位化:

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    if width > height:
    	k = width / height
    	glFrustum(view [0]*k, view [1]*k, view [2], view [3], view [4], view [5])
    else:
    	k = height / width
    	glFrustum(view [0], view [1], view [2]*k, view [3]*k, view [4], view [5])
    

    4.6 设置视点

    视点是和视景体关联的概念。设置视点需要考虑眼睛在哪儿、看哪儿、头顶朝哪儿,分别对应着eye, lookat 和 eye_up 三个向量。

    gluLookAt(
           eye[0], eye[1], eye[2], 
           look_at[0], look_at[1], look_at[2],
           eye_up[0], eye_up[1], eye_up[2]
       )
    

    4.7 设置视口

    视口也是和视景体关联的概念,相对简单一点。

    glViewport(0, 0, width, height)
    

    4.8 设置模型视图

    模型平移、旋转、缩放等几何变换,需要切换到模型矩阵:

    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glScale(1.0, 1.0, 1.0)
    

    4.9 捕捉鼠标事件、键盘事件和窗口事件

    GLUT 库提供了几个函数帮我们捕捉鼠标事件、键盘事件和窗口事件:

    1. glutMouseFunc()
      该函数捕捉鼠标点击和滚轮操作,返回4个参数给被绑定的事件函数:键(左键/右键/中键/滚轮上/滚轮下)、状态(1/0)、x坐标、y坐标

    2. glutMotionFunc()
      该函数捕捉有一个鼠标键被按下时的鼠标移动给被绑定的事件函数,返回2个参数:x坐标、y坐标

    3. glutPassiveMotionFunc()
      该函数捕捉鼠标移动,返回2个参数给被绑定的事件函数:x坐标、y坐标

    4. glutEntryFunc()
      该函数捕捉鼠标离开或进入窗口区域,返回1个参数给被绑定的事件函数:GLUT_LEFT 或者 GLUT_ENTERED

    5. glutKeyboardFunc(keydown)
      该函数捕捉键盘按键被按下,返回3个参数给被绑定的事件函数:被按下的键,x坐标、y坐标

    6. glutReshapeFunc()
      该函数捕捉窗口被改变大小,返回2个参数给被绑定的事件函数:窗口宽度、窗口高度

    如果我们需要捕捉这些事件,只需要定义事件函数,注册相应的函数就行:

    def reshape(width, height):
    	pass
    
    def mouseclick(button, state, x, y):
    	pass
    
    def mousemotion(x, y):
    	pass
    
    def keydown(key, x, y):
    	pass
    
    glutReshapeFunc(reshape)            # 注册响应窗口改变的函数reshape()
    glutMouseFunc(mouseclick)           # 注册响应鼠标点击的函数mouseclick()
    glutMotionFunc(mousemotion)         # 注册响应鼠标拖拽的函数mousemotion()
    glutKeyboardFunc(keydown)           # 注册键盘输入的函数keydown()
    

    4.10 综合应用

    是时候把我们上面讲的这些东西完整的演示一下了。下面的代码还是画了世界坐标系,并在原点前后各画了一个三角形。鼠标可以拖拽视点绕参考点旋转(二者距离保持不变),滚轮可以缩放模型。敲击退格键或回车键可以让视点远离或接近参考点。敲击 x/y/z 可以减小参考点对应的坐标值,敲击 X/Y/Z 可以增大参考点对应的坐标值。敲击空格键可以切换投影模式。
    在这里插入图片描述
    上图左是平行投影模式的显示效果,上图右是透视投影模式的显示效果。代码如下:

    # -*- coding: utf-8 -*-
    
    # -------------------------------------------
    # quidam_02.py 旋转、缩放、改变视点和参考点
    # -------------------------------------------
    
    from OpenGL.GL import *
    from OpenGL.GLU import *
    from OpenGL.GLUT import *
    import numpy as np
    
    IS_PERSPECTIVE = True                               # 透视投影
    VIEW = np.array([-0.8, 0.8, -0.8, 0.8, 1.0, 20.0])  # 视景体的left/right/bottom/top/near/far六个面
    SCALE_K = np.array([1.0, 1.0, 1.0])                 # 模型缩放比例
    EYE = np.array([0.0, 0.0, 2.0])                     # 眼睛的位置(默认z轴的正方向)
    LOOK_AT = np.array([0.0, 0.0, 0.0])                 # 瞄准方向的参考点(默认在坐标原点)
    EYE_UP = np.array([0.0, 1.0, 0.0])                  # 定义对观察者而言的上方(默认y轴的正方向)
    WIN_W, WIN_H = 640, 480                             # 保存窗口宽度和高度的变量
    LEFT_IS_DOWNED = False                              # 鼠标左键被按下
    MOUSE_X, MOUSE_Y = 0, 0                             # 考察鼠标位移量时保存的起始位置
    
    def getposture():
        global EYE, LOOK_AT
        
        dist = np.sqrt(np.power((EYE-LOOK_AT), 2).sum())
        if dist > 0:
            phi = np.arcsin((EYE[1]-LOOK_AT[1])/dist)
            theta = np.arcsin((EYE[0]-LOOK_AT[0])/(dist*np.cos(phi)))
        else:
            phi = 0.0
            theta = 0.0
            
        return dist, phi, theta
        
    DIST, PHI, THETA = getposture()                     # 眼睛与观察目标之间的距离、仰角、方位角
    
    def init():
        glClearColor(0.0, 0.0, 0.0, 1.0) # 设置画布背景色。注意:这里必须是4个参数
        glEnable(GL_DEPTH_TEST)          # 开启深度测试,实现遮挡关系
        glDepthFunc(GL_LEQUAL)           # 设置深度测试函数(GL_LEQUAL只是选项之一)
    
    def draw():
        global IS_PERSPECTIVE, VIEW
        global EYE, LOOK_AT, EYE_UP
        global SCALE_K
        global WIN_W, WIN_H
            
        # 清除屏幕及深度缓存
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        
        # 设置投影(透视投影)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        
        if WIN_W > WIN_H:
            if IS_PERSPECTIVE:
                glFrustum(VIEW[0]*WIN_W/WIN_H, VIEW[1]*WIN_W/WIN_H, VIEW[2], VIEW[3], VIEW[4], VIEW[5])
            else:
                glOrtho(VIEW[0]*WIN_W/WIN_H, VIEW[1]*WIN_W/WIN_H, VIEW[2], VIEW[3], VIEW[4], VIEW[5])
        else:
            if IS_PERSPECTIVE:
                glFrustum(VIEW[0], VIEW[1], VIEW[2]*WIN_H/WIN_W, VIEW[3]*WIN_H/WIN_W, VIEW[4], VIEW[5])
            else:
                glOrtho(VIEW[0], VIEW[1], VIEW[2]*WIN_H/WIN_W, VIEW[3]*WIN_H/WIN_W, VIEW[4], VIEW[5])
            
        # 设置模型视图
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
            
        # 几何变换
        glScale(SCALE_K[0], SCALE_K[1], SCALE_K[2])
            
        # 设置视点
        gluLookAt(
            EYE[0], EYE[1], EYE[2], 
            LOOK_AT[0], LOOK_AT[1], LOOK_AT[2],
            EYE_UP[0], EYE_UP[1], EYE_UP[2]
        )
        
        # 设置视口
        glViewport(0, 0, WIN_W, WIN_H)
        
        # ---------------------------------------------------------------
        glBegin(GL_LINES)                    # 开始绘制线段(世界坐标系)
        
        # 以红色绘制x轴
        glColor4f(1.0, 0.0, 0.0, 1.0)        # 设置当前颜色为红色不透明
        glVertex3f(-0.8, 0.0, 0.0)           # 设置x轴顶点(x轴负方向)
        glVertex3f(0.8, 0.0, 0.0)            # 设置x轴顶点(x轴正方向)
        
        # 以绿色绘制y轴
        glColor4f(0.0, 1.0, 0.0, 1.0)        # 设置当前颜色为绿色不透明
        glVertex3f(0.0, -0.8, 0.0)           # 设置y轴顶点(y轴负方向)
        glVertex3f(0.0, 0.8, 0.0)            # 设置y轴顶点(y轴正方向)
        
        # 以蓝色绘制z轴
        glColor4f(0.0, 0.0, 1.0, 1.0)        # 设置当前颜色为蓝色不透明
        glVertex3f(0.0, 0.0, -0.8)           # 设置z轴顶点(z轴负方向)
        glVertex3f(0.0, 0.0, 0.8)            # 设置z轴顶点(z轴正方向)
        
        glEnd()                              # 结束绘制线段
        
        # ---------------------------------------------------------------
        glBegin(GL_TRIANGLES)                # 开始绘制三角形(z轴负半区)
        
        glColor4f(1.0, 0.0, 0.0, 1.0)        # 设置当前颜色为红色不透明
        glVertex3f(-0.5, -0.366, -0.5)       # 设置三角形顶点
        glColor4f(0.0, 1.0, 0.0, 1.0)        # 设置当前颜色为绿色不透明
        glVertex3f(0.5, -0.366, -0.5)        # 设置三角形顶点
        glColor4f(0.0, 0.0, 1.0, 1.0)        # 设置当前颜色为蓝色不透明
        glVertex3f(0.0, 0.5, -0.5)           # 设置三角形顶点
        
        glEnd()                              # 结束绘制三角形
        
        # ---------------------------------------------------------------
        glBegin(GL_TRIANGLES)                # 开始绘制三角形(z轴正半区)
        
        glColor4f(1.0, 0.0, 0.0, 1.0)        # 设置当前颜色为红色不透明
        glVertex3f(-0.5, 0.5, 0.5)           # 设置三角形顶点
        glColor4f(0.0, 1.0, 0.0, 1.0)        # 设置当前颜色为绿色不透明
        glVertex3f(0.5, 0.5, 0.5)            # 设置三角形顶点
        glColor4f(0.0, 0.0, 1.0, 1.0)        # 设置当前颜色为蓝色不透明
        glVertex3f(0.0, -0.366, 0.5)         # 设置三角形顶点
        
        glEnd()                              # 结束绘制三角形
        
        # ---------------------------------------------------------------
        glutSwapBuffers()                    # 切换缓冲区,以显示绘制内容
        
    def reshape(width, height):
        global WIN_W, WIN_H
        
        WIN_W, WIN_H = width, height
        glutPostRedisplay()
        
    def mouseclick(button, state, x, y):
        global SCALE_K
        global LEFT_IS_DOWNED
        global MOUSE_X, MOUSE_Y
        
        MOUSE_X, MOUSE_Y = x, y
        if button == GLUT_LEFT_BUTTON:
            LEFT_IS_DOWNED = state==GLUT_DOWN
        elif button == 3:
            SCALE_K *= 1.05
            glutPostRedisplay()
        elif button == 4:
            SCALE_K *= 0.95
            glutPostRedisplay()
        
    def mousemotion(x, y):
        global LEFT_IS_DOWNED
        global EYE, EYE_UP
        global MOUSE_X, MOUSE_Y
        global DIST, PHI, THETA
        global WIN_W, WIN_H
        
        if LEFT_IS_DOWNED:
            dx = MOUSE_X - x
            dy = y - MOUSE_Y
            MOUSE_X, MOUSE_Y = x, y
            
            PHI += 2*np.pi*dy/WIN_H
            PHI %= 2*np.pi
            THETA += 2*np.pi*dx/WIN_W
            THETA %= 2*np.pi
            r = DIST*np.cos(PHI)
            
            EYE[1] = DIST*np.sin(PHI)
            EYE[0] = r*np.sin(THETA)
            EYE[2] = r*np.cos(THETA)
                
            if 0.5*np.pi < PHI < 1.5*np.pi:
                EYE_UP[1] = -1.0
            else:
                EYE_UP[1] = 1.0
            
            glutPostRedisplay()
        
    def keydown(key, x, y):
        global DIST, PHI, THETA
        global EYE, LOOK_AT, EYE_UP
        global IS_PERSPECTIVE, VIEW
        
        if key in [b'x', b'X', b'y', b'Y', b'z', b'Z']:
            if key == b'x': # 瞄准参考点 x 减小
                LOOK_AT[0] -= 0.01
            elif key == b'X': # 瞄准参考 x 增大
                LOOK_AT[0] += 0.01
            elif key == b'y': # 瞄准参考点 y 减小
                LOOK_AT[1] -= 0.01
            elif key == b'Y': # 瞄准参考点 y 增大
                LOOK_AT[1] += 0.01
            elif key == b'z': # 瞄准参考点 z 减小
                LOOK_AT[2] -= 0.01
            elif key == b'Z': # 瞄准参考点 z 增大
                LOOK_AT[2] += 0.01
            
            DIST, PHI, THETA = getposture()
            glutPostRedisplay()
        elif key == b'\r': # 回车键,视点前进
            EYE = LOOK_AT + (EYE - LOOK_AT) * 0.9
            DIST, PHI, THETA = getposture()
            glutPostRedisplay()
        elif key == b'\x08': # 退格键,视点后退
            EYE = LOOK_AT + (EYE - LOOK_AT) * 1.1
            DIST, PHI, THETA = getposture()
            glutPostRedisplay()
        elif key == b' ': # 空格键,切换投影模式
            IS_PERSPECTIVE = not IS_PERSPECTIVE 
            glutPostRedisplay()
    
    if __name__ == "__main__":
        glutInit()
        displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH
        glutInitDisplayMode(displayMode)
    
        glutInitWindowSize(WIN_W, WIN_H)
        glutInitWindowPosition(300, 200)
        glutCreateWindow('Quidam Of OpenGL')
        
        init()                              # 初始化画布
        glutDisplayFunc(draw)               # 注册回调函数draw()
        glutReshapeFunc(reshape)            # 注册响应窗口改变的函数reshape()
        glutMouseFunc(mouseclick)           # 注册响应鼠标点击的函数mouseclick()
        glutMotionFunc(mousemotion)         # 注册响应鼠标拖拽的函数mousemotion()
        glutKeyboardFunc(keydown)           # 注册键盘输入的函数keydown()
        
        glutMainLoop()                      # 进入glut主循环    
    

    4.11 小结

    虽然还有很多领域需要我们继续探索,比如灯光、材质、雾化、拾取等,但那不是奇幻之旅的目标。奇幻之旅仅仅是帮助读者建立 OpenGL 的基本概念。至此,我们基本完成了任务。

    5 加速渲染

    实际应用 OpenGL 绘制三维图像时,往往需要处理数以万计的顶点,有时甚至是百万级、千万级。我们通常不会在绘制函数里面传送这些数据,而是在绘制之前,将这些数据提前传送到GPU。绘制函数每次绘制时,只需要从GPU的缓存中取出数据即可,极大地提高了效率。这个机制地实现,依赖于顶点缓冲区对象(Vertex Buffer Object),简称VBO。

    尽管 VBO 是显卡的扩展,其实没有用到GPU运算,也就是说 VBO 不用写着色语言,直接用opengl函数就可以调用,主要目的是用于加快渲染的速。

    VBO 将顶点信息放到 GPU 中,GPU 在渲染时去缓存中取数据,二者中间的桥梁是 GL-Context。GL-Context 整个程序一般只有一个,所以如果一个渲染流程里有两份不同的绘制代码,GL-context 就负责在他们之间进行切换。这也是为什么要在渲染过程中,在每份绘制代码之中会有 glBindbuffer、glEnableVertexAttribArray、glVertexAttribPointer。如果把这些都放到初始化时候完成,使用一种结构记录该次绘制所需要的所有 VBO 所需信息,把它保存到 VBO特定位置,绘制的时候直接在这个位置取信息绘制,会简化渲染流程、提升渲染速度。这就是 VAO 概念产生的初衷。

    VAO 的全名是 Vertex Array Object,首先,它不是 Buffer-Object,所以不用作存储数据;其次,它针对“顶点”而言,也就是说它跟“顶点的绘制”息息相关。VAO 记录的是一次绘制中所需要的信息,这包括“数据在哪里 glBindBuffer”、“数据的格式是怎么样的 glVertexAttribPointer”、shader-attribute 的 location 的启用 glEnableVertexAttribArray。

    根据我查到的资料,几乎所有的显卡都支持 VBO,但不是所有的显卡都支持 VAO,而 VAO 仅仅是优化了 VBO 的使用方法,对于加速并没有实质性的影响,因此本文只讨论 VBO 技术。

    5.1 创建顶点缓冲区对象(VBO)

    假定画一个六面体,顶点是这样的:

    # 六面体数据
    # ------------------------------------------------------
    #    v4----- v5
    #   /|      /|
    #  v0------v1|
    #  | |     | |
    #  | v7----|-v6
    #  |/      |/
    #  v3------v2
    
    # 顶点集
    vertices = np.array([
        -0.5, 0.5, 0.5,   0.5, 0.5, 0.5,   0.5, -0.5, 0.5,   -0.5, -0.5, 0.5, # v0-v1-v2-v3
        -0.5, 0.5, -0.5,  0.5, 0.5, -0.5,  0.5, -0.5, -0.5,  -0.5, -0.5, -0.5 # v4-v5-v6-v7
    ], dtype=np.float32)
    
    # 索引集
    indices = np.array([
        0, 1, 2, 3, # v0-v1-v2-v3 (front)
        4, 5, 1, 0, # v4-v5-v1-v0 (top)
        3, 2, 6, 7, # v3-v2-v6-v7 (bottom)
        5, 4, 7, 6, # v5-v4-v7-v6 (back)
        1, 5, 6, 2, # v1-v5-v6-v2 (right)
        4, 0, 3, 7  # v4-v0-v3-v7 (left)
    ], dtype=np.int)
    

    在GPU上创建VBO如下:

    from OpenGL.arrays import vbo
    
    vbo_vertices = vbo.VBO(vertices)
    vbo_indices = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER)
    

    创建 顶点 VBO 时,默认 target=GL_ARRAY_BUFFER, 而创建索引 VBO 时,target=GL_ELEMENT_ARRAY_BUFFER,因为顶点的数据类型是 np.float32,索引的数据类型是np.int。

    在VBO保存的顶点数据集,除了顶点信息外,还可以包含颜色、法线、纹理等数据,这就是顶点混合数组的概念。假定我们在上面的顶点集中增加每个顶点的颜色,则可以写成这样:

    vertices = np.array([
        0.3, 0.6, 0.9, -0.35, 0.35, 0.35,   # c0-v0
        0.6, 0.9, 0.3, 0.35, 0.35, 0.35,    # c1-v1
        0.9, 0.3, 0.6, 0.35, -0.35, 0.35,   # c2-v2 
        0.3, 0.9, 0.6, -0.35, -0.35, 0.35,  # c3-v3 
        0.6, 0.3, 0.9, -0.35, 0.35, -0.35,  # c4-v4 
        0.9, 0.6, 0.3, 0.35, 0.35, -0.35,   # c5-v5 
    	0.3, 0.9, 0.9, 0.35, -0.35, -0.35,  # c6-v6 
    	0.9, 0.9, 0.3, -0.35, -0.35, -0.35  # c7-v7
    ], dtype=np.float32)
    

    5.2 分离顶点混合数组

    使用 glInterleavedArrays() 函数可以从顶点混合数组中分离顶点、颜色、法线和纹理。比如,对只包含顶点信息的顶点混合数组:

    vbo_indices.bind()
    glInterleavedArrays(GL_V3F, 0, None)
    

    如果顶点混合数组包含了颜色和顶点信息:

    vbo_indices.bind()
    glInterleavedArrays(GL_C3F_V3F, 0, None)
    

    glInterleavedArrays() 函数第一个参数总共有14个选项,分别是:

    • GL_V2F
    • GL_V3F
    • GL_C4UB_V2F
    • GL_C4UB_V3F
    • GL_C3F_V3F
    • GL_N3F_V3F
    • GL_C4F_N3F_V3F
    • GL_T2F_V3F
    • GL_T4F_V4F
    • GL_T2F_C4UB_V3F
    • GL_T2F_C3F_V3F
    • GL_T2F_N3F_V3F
    • GL_T2F_C4F_N3F_V3F
    • GL_T4F_C4F_N3F_V4F

    5.3 使用顶点缓冲区对象(VBO)

    使用glDrawElements() 等函数绘制前,需要先绑定顶点数据集和索引数据集,然后使用glInterleavedArrays() 分理出顶点、颜色、法线等数据。

    vbo_indices.bind()
    glInterleavedArrays(GL_V3F, 0, None)
    vbo_indices.bind()
    glDrawElements(GL_QUADS, int(vbo_indices .size/4), GL_UNSIGNED_INT, None)
    vbo_indices.unbind()
    vbo_indices.unbind()
    

    6 致谢

    写作过程中,我参考了很多资料,包括纸质书籍和网页,列写于此,一并致谢!

    1. 《OpenGL编程精粹》杨柏林 陈根浪 徐静 编著
    2. Opengl开发库介绍
    3. OpenGL的API函数使用手册
    4. glut处理鼠标事件
    5. Learn OpenGL

    本文写作过程持续了两三周,期间可谓呕心沥血。发表之际,如释重负,填词以记之。

    愁云淡淡风萧萧,
    暮暮复朝朝。
    别来应是,体重锐减,骨立形销。
    
    日日思OpenGL,
    情绪好无聊。
    一篇博文,一台电脑,一只鼠标。
    
    ——调寄《眼儿媚》
    

    7. 后记

    近期有很多朋友通过私信咨询有关Python学习问题。为便于交流,我在CSDN的app上创建了“Python作业辅导”大本营,面向Python初学者,为大家提供咨询服务、辅导Python作业。欢迎有兴趣的同学使用微信扫码加入。

    在这里插入图片描述

    从博客到公众号,每一篇、每一题、每一句、每一行代码,都坚持原创,绝不复制抄袭,这是我坚守的原则。如果喜欢,请关注我的微信公众号“Python作业辅导员”。

    在这里插入图片描述

    展开全文
  • OpenGL入门教程

    万次阅读 多人点赞 2018-12-03 18:14:53
    OpenGL OpenGL是渲染2D、3D矢量图形硬件的一种软件接口。本质上说,它是一个3D图形和模型库,具有高度的可移植性,并且具有非常快的渲染速度。OpenGL并不是一种语言,而是更像一个C运行时函数库。它提供了一些预包装...
  • OpenGLOpenGl ES简介

    千次阅读 2018-03-04 22:56:43
    OpenGL的基本认识: OpenGL是什么?(开发的图形库) OpenGL可以来干什么?(应用领域:视频 图形 图片处理,2D/3d游戏引擎开发,科学可视化,医学软件的开发,CAD(计算机辅助技术),虚拟实境(AR VR),AI人工智能)等等...
  • QT + OpenGL

    千次阅读 2016-03-21 14:30:26
    OpenGL
  • OpenGL介绍

    千次阅读 2018-12-19 16:50:35
    前言:本文章的内容是基于OpenGL教程做的总结。 一.首先要明白OpenGL是什么 Opengl不是一个语言,它通常被认为是一个图形接口库,(我一直都是这么理解的),但更准确地说OpenGL本身并不是API,它仅仅是一个规范。...
  • opengl各类库

    千次下载 热门讨论 2012-12-03 18:26:51
    opengl各类库,其中有GL.H glaux.dll GLAUX.H glut32.dll GLU32.LIB glut32.lib opengl32.dll OPENGL32.LIB等等
  • Android C++ OpenGL 教程

    千人学习 2019-02-14 23:05:43
    用纯C++实现Android的OpenGL渲染功能,包括EGL环境创建、EGL线程创建、OpenGL生命周期管理等,会结合SurfaceView和TextureView实现OpenGL的渲染,最终我们会实现一个YUV播放器实例,为音视频开发打下坚实的基础。
  • Could NOT find OpenGL (missing: OPENGL_opengl_LIBRARY OPENGL_glx_LIBRARY OPENGL_INCLUDE_DIR) sudo apt-fast install libgl1-mesa-dev
  • OpenGL ES】OpenGL ES简介

    千次阅读 2017-04-25 20:12:48
    【参考-khronos】https://www.khronos.org/opengles/1、简介OpenGL ES(OpenGL for Embeded System)是OpenGL(Open Graphics Library)的精简子集,是以手持和嵌入式设备为目标的高级3D图形API,如现在火爆的智能...
  • OpenGL超级宝典 第5版 中文版 pdf

    千次下载 热门讨论 2013-07-21 16:16:45
    OpenGL超级宝典(第5版)》是OpenGL及3D图形编程最好的入门指南,涵盖了使用最新版本的OpenGL进行编程所需要的主要知识。全书分三部分,共16章,另有3个附录。第一部分包括第1章到第7章,介绍如何构建一个使用...
  • OpenGL 安装

    千次阅读 2018-12-23 23:41:24
    OpenGL 是一套由SGI公司发展出来的绘图函数库,它是一组 C 语言的函数,用于 2D 与 3D 图形应用程序的开发上。OpenGL 让程序开发人员不需要考虑到各种显示卡底层运作是否相同的问题,硬件由 OpenGL 核心去沟通,因此...
  • openGL 3D图形和openGL简介

    千次阅读 2017-07-13 20:38:18
    基本概念与说明OpenGL是一个图形API,用来绘制三维物体(也可以是2D物体),OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三维图形 API 的子集。 Android平台下,对于OpenGL ES有一套Java的封装,唯一非Java...
  • OpenGLES与OpenGL的区别

    万次阅读 2017-03-16 00:22:38
    早先定义OpenGL ES是OpenGL的嵌入式设备版本,但由于嵌入式设备要求的是高性能,所以一些其它纯追求高性能的设备也开始用这种API方式,比如 SONY PlayStation 3。   OpenGL ES相对OpenGL删减了一切低效能的操作...
  • OpenGL ES总结(一)OpenGL 初识

    万次阅读 多人点赞 2017-03-12 13:55:04
    OpenGL是在图形图像中,非常优秀的渲染库,文中Demo下载地址:https://github.com/hejunlin2013/OpenGL31,看下今天的Agenda:
  • OpenGL ES2.0基础

    万人学习 2015-05-27 16:39:31
    初级学习OpenGL ES2.0的课程,从无到有,从进本的函数讲起,每一课时都附带一个例子程序。深入浅出的讲解可编程管线技术,令人费解的文理,以及混合技术,各种优化技术:顶点缓冲区,索引缓冲区,帧缓冲区,介绍精灵...
  • [OpenGL]OpenGL库函数汇总

    千次阅读 2014-05-04 10:29:29
    OpenGL函数库相关的API有核心库(gl)、实用库(glu)、辅助库(aux)、实用工具库(glut)、窗口库(glx、agl、wgl)和扩展函数库等。从图可以看出,gl是核心,glu是对gl的部分封装。glx、agl、wgl 是针对不同窗口系统的函数...
  • OpenGL概述 OpenGL(OpenGraphicsLibrary 开发图形库)是一个跨编程语言、跨平台的三维的计算机图形模型库。 OpenGL是SGI公司开发的一套计算机图形处理系统,是图形硬件的软件接口,任何一个OpenGL应用程序无须考虑其...
  • OpenGL OpenGL ES 简介及其功能

    千次阅读 2018-07-27 11:08:36
    OpenGL(全写Open Graphics Library)是一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它是一个功能强大,调用方便的底层图形库。 OpenGL是一个开放的三维图形软件包,它独立于窗口系统和操作系统,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 85,097
精华内容 34,038
关键字:

opengl