logo资料库

learnopengl 中文版 pdf.pdf

第1页 / 共471页
第2页 / 共471页
第3页 / 共471页
第4页 / 共471页
第5页 / 共471页
第6页 / 共471页
第7页 / 共471页
第8页 / 共471页
资料共471页,剩余部分请下载后查看
Introduction
入门
创建窗口
你好,窗口
你好,三角形
着色器
纹理
变换
坐标系统
摄像机
复习
光照
光照基础
材质
光照贴图
投光物
多光源
复习
加载模型
网格
模型
高级OpenGL
模板测试
混合
面剔除
帧缓冲
立方体贴图
高级数据
高级GLSL
几何着色器
实例化
抗锯齿
高级光照
Gamma校正
阴影-阴影映射
阴影-点光源阴影
阴影-CSM
法线贴图
视差贴图
HDR
泛光
延迟着色法
SSAO
实战
Breakout
SSAO
LearnOpenGL-CN Table of Contents Introduction 入门 创建窗口 你好,窗口 你好,三角形 着色器 纹理 变换 坐标系统 摄像机 复习 光照基础 材质 光照贴图 投光物 多光源 光照 复习 加载模型 网格 模型 高级OpenGL 模板测试 混合 面剔除 帧缓冲 立方体贴图 高级数据 高级GLSL 几何着色器 0 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.1 2.2 2.3 2.4 2.5 2.6 3 3.1 3.2 4 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 2
LearnOpenGL-CN 实例化 抗锯齿 高级光照 Gamma校正 阴影-阴影映射 阴影-点光源阴影 阴影-CSM 法线贴图 视差贴图 HDR 泛光 延迟着色法 SSAO 实战 Breakout SSAO 4.9 4.10 5 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 6 6.1 6.2 3
LearnOpenGL-CN My Awesome Book This file serves as your book's preface, a great place to describe your book's content and ideas. Introduction 4
LearnOpenGL-CN OpenGL (Open Graphics Library) 原文 OpenGL 作者 翻译 校对 JoeyDeVries gjy_1992 Geequlim 在开始这段旅程之前我们先了解一下OpenGL到底是什么。一般它被认为是一个应用程序编程 接口(Application Programming Interface, API),它包含了一系列可以操作图形、图像的方 法。然而,OpenGL本身并不是一个API,仅仅是一个规范,由Khronos组织制定并维护。 OpenGL严格规定了每个函数该如何执行,以及它们该如何返回。至于内部具体每个函数是如 何实现的,将由OpenGL库的开发者自行决定(注:这里开发者是指编写OpenGL库的人)。因 为OpenGL规范并没有规定实现的细节,具体的OpenGL库允许使用不同的实现,只要其功能 和结果与规范相匹配(亦即,作为用户不会感受到功能上的差异)。 实际的OpenGL库的开发者通常是显卡的生产商。每个你购买的显卡都会支持特定版本的 OpenGL,通常是为一个系列的显卡专门开发的。当你使用苹果系统的时候,OpenGL库是由 苹果自身维护的。在Linux下,有显卡生产商提供的OpenGL库,也有一些爱好者改编的版 本。这也意味着任何时候OpenGL库表现的行为与规范规定的不一致时,基本都是库的开发者 留下的bug。(快甩锅) !!! Important 由于OpenGL的大多数实现都是由显卡厂商编写的,当产生一个bug时通常可以通过升级显卡驱动来解决。这些驱动会包括你的显卡能支持的最新版本的OpenGL,这也是为什么总是建议你偶尔更新一下显卡驱动。 所有版本的OpenGL规范书都被寄存在Khronos那里,并且都是公开的。有兴趣的读者可以找 到OpenGL3.3(我们将要使用的版本)的规范书。如果你想深入到OpenGL的细节(只关心函数 的功能描述而不是函数的实现),这是个很好的选择。该规范还提供一个强大的可以寻找到每 个函数具体功能的参考。 核心模式(Core-profile)与立即渲染模式 (Immediate mode) 早期的OpenGL使用立即渲染模式(也就是固定渲染管线),这个模式下绘制图形很方便。 OpenGL的大多数功能都被库隐藏起来,开发者很少能控制OpenGL如何进行计算。而开发者 希望更多的灵活性。随着时间推移,规范越来越灵活,开发者也能更多的控制绘图细节。立 入门 5
LearnOpenGL-CN 即渲染模式确实容易使用和理解,但是效率太低。因此从OpenGL3.2开始,规范书开始废弃 立即渲染模式,推出核心模式,这个模式完全移除了旧的特性。 当使用核心模式时,OpenGL迫使我们使用现代的做法。当我们试图使用一个废弃的函数时, OpenGL会抛出一个错误并终止绘图。现代做法的优势是更高的灵活性和效率,然而也更难于 学习。立即渲染模式从OpenGL实际操作中抽象掉了很多细节,因而它易于学习的同时,也很 难去把握OpenGL具体是如何操作的。现代做法要求使用者真正理解OpenGL和图形编程,它 有一些难度,然而提供了更多的灵活性,更高的效率,更重要的是可以更深入的理解图形编 程。 这也是为什么我们的教程面向OpenGL3.3的核心模式。虽然上手更困难,但是值得去努力。 现今更高版本的OpenGL已经发布(目前最新是4.5),你可能会问:为什么我们还要学习3.3? 答案很简单,所有OpenGL的更高的版本都是在3.3的基础上,添加了额外的功能,并不更改 进核心架构。新版本只是引入了一些更有效率或更有用的方式去完成同样的功能。因此所有 的概念和技术在现代OpenGL版本里都保持一致。当你的经验足够,你可以轻松使用来自更高 版本OpenGL的新特性。 !!! Attention 当使用新版本的OpenGL特性时,只有新一代的显卡能够支持你的应用程序。这也是为什么大多数开发者基于较低版本的OpenGL编写程序,并有选择的启用新特性。 在有些教程里你会发现像如下方式注明的新特性。 扩展(Extension) OpenGL的一大特性就是对扩展的支持,当一个显卡公司提出一个新特性或者渲染上的大优 化,通常会以扩展的方式在驱动中实现。如果一个程序在支持这个扩展的显卡上运行,开发 者可以使用这个扩展提供的一些更先进更有效的图形功能。通过这种方式,开发者不必等待 一个新的OpenGL规范面世,就可以方便的检查显卡是否支持此扩展。通常,当一个扩展非常 流行或有用的时候,它将最终成为未来的OpenGL规范的一部分。 使用扩展的代码大多看上去如下: if(GL_ARB_extension_name) { // 使用一些新的特性 } else { // 不支持此扩展: 用旧的方式去做 } 入门 6
LearnOpenGL-CN 使用OpenGL3.3时,我们很少需要使用扩展来完成大多数功能,但是掌握这种方式是必须 的。 状态机(State Machine) OpenGL自身是一个巨大的状态机:一个描述OpenGL该如何操作的所有变量的大集合。 OpenGL的状态通常被称为OpenGL上下文(Context)。我们通常使用如下途径去更改OpenGL 状态:设置一些选项,操作一些缓冲。最后,我们使用当前OpenGL上下文来渲染。 假设当我们想告诉OpenGL去画线而不是三角形的时候,我们通过改变一些上下文变量来改变 OpenGL状态,从而告诉OpenGL如何去绘图。一旦我们改变了OpenGL的状态为绘制线段, 下一个绘制命令就会画出线段而不是三角形。 用OpenGL工作时,我们会遇到一些状态设置函数(State-changing Function),以及一些在这 些状态的基础上状态应用的函数(State-using Function)。只要你记住OpenGL本质上是个大状 态机,就能更容易理解它的大部分特性。 对象(Object) OpenGL库是用C语言写的,同时也支持多种语言的派生,但是核心是一个C库。一些C语言 的结构不易被翻译到其他高层语言,因此OpenGL设计的时候引入了一些抽象概念。“对象”就 是其中一个。 在OpenGL中一个对象是指一些选项的集合,代表OpenGL状态的一个子集。比如,我们可以 用一个对象来代表绘图窗口的设置,可以设置它的大小、支持的颜色位数等等。可以把对象 看做一个C风格的结构体: struct object_name { GLfloat option1; GLuint option2; GLchar[] name; }; !!! Important **原始类型(Primitive Type)** 使用OpenGL时,建议使用OpenGL定义的原始类型。比如使用`float`时我们加上前缀GL(因此写作`GLfloat`)。`int`,`uint`,`char`,`bool`等等类似。OpenGL定义的这些GL原始类型是平台无关的内存排列方式。而int等原始类型在不同平台上可能有不同的内存排列方式。使用GL原始类型可以保证你的程序在不同的平台上工作一致。 当我们使用一个对象时,通常看起来像如下一样(把OpenGL上下文比作一个大的结构体): 入门 7
LearnOpenGL-CN // OpenGL的状态 struct OpenGL_Context { ... object* object_Window_Target; ... }; // 创建对象 GLuint objectId = 0; glGenObject(1, &objectId); // 绑定对象至上下文 glBindObject(GL_WINDOW_TARGET, objectId); // 设置GL_WINDOW_TARGET对象的一些选项 glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH, 800); glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600); // 将上下文的GL_WINDOW_TARGET对象设回默认 glBindObject(GL_WINDOW_TARGET, 0); 这一小片代码将会是以后使用OpenGL时常见的工作流。我们首先创建一个对象,然后用一个 id保存它的引用(实际数据被储存在后台)。然后我们将对象绑定至上下文的目标位置(例子里窗 口对象的目标位置被定义成 GL_WINDOW_TARGET )。接下来我们设置窗口的选项。最后我们通过 将目标位置的对象id设回0的方式解绑这个对象。设置的选项被保存在 objectId 代表的对象 中,一旦我们重新绑定这个对象到 GL_WINDOW_TARGET 位置,这些选项就会重新生效。 !!! Attention 目前提供的示例代码只是OpenGL如何操作的一个大致描述,通过阅读以后的教程你会遇到很多实际的例子。 使用对象的一个好处是我们在程序中不止可以定义一个对象并且设置他们的状态,在我们需 要进行一个操作的时候,只需要绑定预设了需要设置的对象即可。比如,有一个作为3D模型 的数据(一栋房子或一个人物,由多个子模型构成)容器对象,在我们想绘制其中任何一个3D 模型的时候,只需绑定相应的子模型数据的对象(我们预先创建并设置好了它们的选项)就可以 了。拥有数个这样的对象允许我们指定多个模型,在想画其中任何一个的时候,简单的将相 应的对象绑定上去,便不需要再进行重复的设置选项的操作了。 让我们开始吧 你现在已经知道一些OpenGL的相关知识了,包括OpenGL作为规范和库,OpenGL大致的操 作流程,以及一些使用扩展的小技巧。不要担心没有你还完全消化它们,通过后面的教程我 们会仔细地讲解每一步,你会通过足够的例子来把握OpenGL。如果你已经做好了开始下一步 入门 8
分享到:
收藏