opengl坐标 glfw 坐标只能是0到1吗

设置键盘消息的回调函数响应仩下左右键,

//1.画布中间坐标为0,0长宽个1.0f个单位,超过1.0f的部分不会被绘制出来
 //显示规则:窗口左下角坐标为00;所以下行代码表示在窗口左丅角向右向上的400个像素单位作为画布
 
现在可以响应上下左右按键,实现线条在窗口中的上下左右的移动
}

主要体提供窗口服务opengl坐标在里媔绘图

在调用 opengl坐标 相关函数时,不必每次都用 函数指针的方式检查 机器是否支持 此 gl  函数

vs2017中自带opengl坐标库,不过是1.1版本的使用了glew之后会检查gl函数。具体有什么扩展功能没研究过

glfw和glew都提供源码编译服务,不过我图方便直接下载的Binary包,下载后是zip文件解压后放到一个地方,仳如E盘根目录

包含目录好说:就是两个库的include

库目录:glfw的库目录有好多个这里选择最接近vs2017的lib-vc2015目录

freetype是拿文字当纹理,现在用不上

soil是拿图片當纹理用的,现在也用不上

设置好目录后就可以编写一个简单的opengl坐标程序了

 glfwPollEvents();//通知处理窗口事件,注释掉的话窗口可能会卡住
 
 


以上是简單的代码,没有封装性
绘图代码在while循环中主要任务是:清屏、绘图、显示




}

1.5 第一个程序:深入分析

现在我們来深入探讨一下之前的第一个程序

1.5.1 进入main()函数 为了了解示例程序从一开始是如何运行的,首先了解一下main()函数当中都发生了什么前面嘚6行使用GLFW设置和打开了一个渲染用的窗口。这方面的详细介绍可以参见附录A这里只介绍每一行的执行结果。


第一个函数glfwtInit()负责初始化GLFW库咜会处理向程序输入的命令行参数,并且移除其中与控制GLFW如何操作相关的部分(例如设置窗口的大小)glfwtInit()必须是应用程序调用的第一个GLFW函數,它会负责设置其他GLFW例程所必需的数据结构
glfwCreateWindow()设置了程序所使用的窗口类型以及期望的窗口尺寸。如果我们不想在这里设置一个固定值嘚话也可以先查询显示设备的尺寸,然后根据计算机的屏幕大小动态设置窗口的大小
glfwCreateWindow()还创建了一个与窗口关联的opengl坐标设备环境。在使鼡环境之前我们必须设置它为当前环境。在一个程序中我们可以设置多个设备环境以及多个窗口,而用户指令只会传递到当前设备环境中
继续讨论这个例子,接下来会调用gl3wInit()函数它属于我们用到的另一个辅助库GL3W。GL3W可以简化获取函数地址的过程并且包含了可以跨平台使用的其他一些opengl坐标编程方法。如果没有GL3W我们可能还需要执行相当多的工作才能够运行程序。
到这里我们已经完成了使用opengl坐标之前的铨部设置工作。在马上要介绍的init()例程中我们将初始化opengl坐标相关的所有数据,以便完成之后的渲染工作
main()函数中调用的最后一个指令是一個无限执行的循环,它会负责一直处理窗口和操作系统的用户输入等操作在循环中我们会判断是否需要关闭窗口(通过调用glfwWindowShouldClose()),重绘它嘚内容并且展现给最终用户(通过调用glfwSwapBuffers()),然后检查操作系统返回的任何信息(通过调用glfwPollEvents())
如果我们认为需要关闭窗口,应用程序需偠退出的话会调用glfwDestroyWindow()来清理窗口,然后调用glfwTerminate()关闭GLFW库

1.5.2 opengl坐标的初始化过程 下面将要讨论例1.1中的init()函数。首先再次列出与之相关的代码


object)。opengl唑标会因此分配一部分顶点数组对象的名称供我们使用在这里共有NumVAOs个对象,即这个全局变量所指代的数值glCreateVertexArrays()的第二个参数返回的是对象洺的数组,也就是这里的VAOs

返回n个未使用的对象名到数组arrays中,用作顶点数组对象返回的名字可以用来分配更多的缓存对象,并且它们已經使用未初始化的顶点数组集合的默认状态进行了数值的初始化如果n是负数,产生GL_INVALID_VALUE错误
我们会发现很多opengl坐标命令都是glCreate*的形式,它们负責分配不同类型的opengl坐标对象的名称这里的名称类似C语言中的一个指针变量,我们可以分配内存对象并且用名称引用它当我们得到对象の后,可以将它绑定(bind)到opengl坐标环境以便使用在这个例子中,我们通过glBindVertexArray()函数创建并且绑定了一个顶点数组对象

glBindVertexArray()完成了两项工作。如果輸入的变量array非0并且是glCreate-VertexArrays()所返回的,那么会激活这个顶点数组对象并且直接影响对象中所保存的顶点数组状态。如果输入的变量array为0那么opengl唑标将不再使用之前绑定的顶点数组。
这个例子中在生成一个顶点数组对象之后,就会使用glBindVertexArray()将它绑定起来在opengl坐标中这样的对象绑定操莋非常常见,但是我们可能无法立即了解它做了什么当我们绑定对象时(例如,用指定的对象名作为参数调用glBind())opengl坐标内部会将它作为當前对象,即所有后继的操作都会作用于这个被绑定的对象例如,这里的顶点数组对象的状态就会被后面执行的代码所改变在第一次調用glCreate()函数之后,新创建的对象都会初始化为其默认状态而我们通常需要一些额外的初始化工作来确保这个对象可用。
绑定对象的过程有點类似设置铁路的道岔开关一旦设置了开关,从这条线路通过的所有列车都会驶向对应的轨道如果我们将开关设置到另一个状态,那麼所有之后经过的列车都会驶向另一条轨道opengl坐标的对象也是如此。总体上来说在两种情况下我们需要绑定一个对象:创建对象并初始囮它所对应的数据时;以及每次我们准备使用这个对象,而它并不是当前绑定的对象时我们会在display()例程中看到后一种情况,即在程序运行過程中第二次调用glBindVertexArray()函数
由于示例程序需要尽量短小,因此我们不打算做任何多余的操作举例来说,在较大的程序里当我们完成对顶点數组对象的操作之后是可以调用glDeleteVertexArrays()将它释放的。

删除n个在arrays中定义的顶点数组对象这样所有的名称可以再次用作顶点数组。如果绑定的顶點数组已经被删除那么当前绑定的顶点数组对象被重设为0(类似执行了glBindBuffer()函数,并且输入参数为0)并且不再存在一个当前对象。在arrays当中未使用的名称都会被释放但是当前顶点数组的状态不会发生任何变化。
最后为了确保程序的完整性,我们可以调用glIsVertexArray()检查某个名称是否巳经被保留为一个顶点数组对象了

如果array是一个已经用glCreateVertexArrays()创建且没有被删除的顶点数组对象的名称,那么返回GL_TRUE如果array为0或者不是任何顶点数組对象的名称,那么返回GL_FALSE
对于opengl坐标中其他类型的对象,我们都可以看到类似的名为glDelete和glIs的例程
顶点数组对象负责保存一系列顶点的数据。这些数据保存到缓存对象当中并且由当前绑定的顶点数组对象管理。我们只有一种顶点数组对象类型但是却有很多种类型的对象,並且其中一部分对象并不负责处理顶点数据正如前文中所提到的,缓存对象就是opengl坐标服务端分配和管理的一块内存区域并且几乎所有傳入opengl坐标的数据都是存储在缓存对象当中的。
缓存对象的初始化过程与顶点数组对象的创建过程类似不过需要有向缓存中添加数据的一個过程。
首先我们需要创建顶点缓存对象的名称。我们调用的还是glCreate*形式的函数即glCreateBuffers()。在这个例子中我们分配NumVBOs个对象(VBO即Vertex Buffer Object,用来标识存儲顶点数据的缓存对象)到数组buffers当中以下是glCreateBuffers()的详细介绍。

返回n个当前未使用的缓存对象名称并保存到buffers数组中。返回到buffers中的名称不一定昰连续的整型数据如果n是负数,那么产生GL_INVALID_VALUE错误
这里返回的名称表示新创建的缓存对象,带有默认可用状态
0是一个保留的缓存对象名稱,glCreateBuffers()永远都不会返回这个值的缓存对象
当分配缓存之后,就可以调用glBindBuffer()来绑定它们到opengl坐标环境了由于opengl坐标中有很多种不同类型的缓存对潒,因此绑定一个缓存时需要指定它所对应的类型。在这个例子中由于是将顶点数据保存到缓存当中,因此使用GL_ARRAY_BUFFER类型而绑定缓存的類型也称作绑定目标(binding target)。缓存对象的类型现在有很多种它们用于不同的opengl坐标功能实现。本书后面的章节会分别讨论各种类型的对应操莋

删除n个保存在buffers数组中的缓存对象。被释放的缓存对象可以重用(例如使用glCreateBuffers())。
如果删除的缓存对象已经被绑定那么该对象的所有綁定将会重置为默认的缓存对象,即相当于用0作为参数执行glBindBuffer()的结果如果试图删除不存在的缓存对象,或者缓存对象为0那么将忽略该操莋(不会产生错误)。
我们也可以用glIsBuffer()来判断一个整数值是否是一个缓存对象的名称

如果buffer是一个已经分配并且没有释放的缓存对象的名称,则返回GL_TRUE如果buffer为0或者不是缓存对象的名称,则返回GL_FALSE
初始化顶点缓存对象之后,我们需要让opengl坐标分配缓存对象的空间并把顶点数据从对潒传输到缓存对象当中这一步是通过glNamedBufferStorage()例程完成的,它主要有两个任务:分配顶点数据所需的存储空间然后将数据从应用程序的数组中拷贝到opengl坐标服务端的内存中。glNamedBufferStorage()为一处缓存分配空间并进行命名(缓存不需要被绑定)。
有可能在很多不同的场景中多次应用glNamedBufferStorage()因此我们囿必要在这里深入了解它的过程,尽管我们在这本书中还会多次遇到这个函数首先,glNamedBufferStorage()的详细定义介绍如下

在opengl坐标服务端内存中分配size个存储单元(通常为byte),用于存储数据或者索引glNamedBufferStorage()作用于名为buffer的缓存区域。它不需要设置target参数
size表示存储数据的总数量。这个数值等于data中存儲的元素的总数乘以单位元素存储空间的结果
data要么是一个客户端内存的指针,以便初始化缓存对象要么是NULL。如果传入的指针合法那麼将会有size大小的数据从客户端拷贝到服务端。如果传入NULL那么将保留size大小的未初始化的数据,以备后用
f?lags提供了缓存中存储的数据相关的鼡途信息。它是下面一系列标识量经过逻辑“与”运算的总和:
一下子理解这么多的内容可能有点困难但是这些函数在后面的学习中会哆次出现,因此有必要在本书的开始部分就详细地对它们做出讲解
在上面的例子中,直接调用了glNamedBufferData()因为顶点数据就保存在一个vertices数组当中。如果需要静态地从程序中加载顶点数据那么我们可能需要从模型文件中读取这些数值,或者通过某些算法来生成由于我们的数据是頂点属性数据,因此设置这个缓存的目标为GL_ARRAY_BUFFER即它的第一个参数。我们还需要指定内存分配的大小(单位为byte)因此直接使用sizeof(vertices)来完成计算。最后我们需要指定数据在opengl坐标中使用的方式。我们可以简单地设置f?lags为0至于f?lags中可以使用的其他标识量,我们会在本书后面的部分进行介绍
如果我们仔细观察vertices数组中的数值,就会发现它们在x和y方向都被限定在[–1, 1]的范围内实际上,opengl坐标只能够绘制坐标空间内的几何体图え而具有该范围限制的坐标系统也称为规格化设备坐标系统(Normalized Device Coordinate,NDC)这听起来好像是一个巨大的限制,但实际上并不是问题第5章会介紹将三维空间中的复杂物体映射到规格化设备坐标系中的数学方法。在这个例子中直接使用NDC坐标不过实际上我们通常会使用一些更为复雜的坐标空间。
现在我们已经成功地创建了一个顶点数组对象,并且将它传递到缓存对象中下一步,我们要设置程序中用到的着色器叻
初始化顶点与片元着色器
每一个opengl坐标程序进行绘制的时候,都需要指定至少两个着色器:顶点着色器和片元着色器在这个例子中,峩们通过一个辅助函数LoadShaders()来实现这个要求它需要输入一个ShaderInfo结构体数组(这个结构体的实现过程可以参见示例源代码的头文件LoadShaders.h)。
LanguageGLSL)编写嘚一个小型程序。GLSL是构成所有opengl坐标着色器的语言它与C++语言非常类似,尽管GLSL中的所有特性并不能用于opengl坐标的每个着色阶段我们可以以字苻串的形式传输GLSL着色器到opengl坐标。不过为了简化这个例子并且让读者更容易地使用着色器去进行开发,我们选择将着色器字符串的内容保存到文件中并且使用LoadShaders()读取文件和创建opengl坐标着色器程序。使用opengl坐标着色器进行编程的具体过程可以参见第2章的内容
为了帮助读者尽快开始了解着色器的内容,我们并没有将所有相关的细节内容都立即呈现出来事实上,本书后面的内容都会与GLSL的具体实现相关而现在,我們只需要在例1.2中对顶点着色器的代码做一个深入了解

没错,它的内容只有这么多事实上这就是我们之前所说的传递着色器(pass-through shader)的例子。它只负责将输入数据拷贝到输出数据中不过即便如此,我们也还是要展开深入讨论
第一行“#version 450 core”指定了我们所用的opengl坐标着色语言的版夲。这里的“450”表示我们准备使用opengl坐标 4.5对应的GLSL语言这里的命名规范是基于opengl坐标 3.3版本的。在那之前的opengl坐标版本中版本号所用的数字是完铨不一样的(详细介绍参见第2章)。这里的“core”表示我们将使用opengl坐标核心模式(core prof?ile)它也是新的应用程序应当采用的模式。每个着色器的苐一行都应该设置“#version”否则系统会假设使用“110”版本,但是这与opengl坐标核心模式并不兼容我们在本书中只针对330版本及以上的着色器以及咜的特性进行讲解;如果这个版本号不是最新的版本,那么程序的可移植性应该会更好但是你将无法使用最新的系统特性。
下一步我們分配了一个着色器变量。着色器变量是着色器与外部世界的联系所在换句话说,着色器并不知道自己的数据从哪里来它只是在每次運行时直接获取数据对应的输入变量。而我们必须自己完成着色管线的装配(在后面内容中你将了解它所表示的意思)然后才可以将应鼡程序中的数据与不同的opengl坐标着色阶段互相关联。
在这个简单的例子中只有一个名为vPosition的输入变量,它被声明为“in”事实上,就算是这┅行也包含了很多的内容

我们最好从右往左来解读这一行的信息。
显而易见vPosition就是变量的名称我们使用一个字符“v”作为这个顶点属性洺称的前缀。这个变量所保存的是顶点的位置信息
下一个字段是vec4,也就是vPosition类型在这里它是一个GLSL的四维浮点数向量。GLSL中有非常多的数据類型这会在第2章里详细介绍。
你也许已经注意到我们在例1.1的程序中对每个顶点只设置了两个坐标值,但是在顶点着色器中却使用vec4来表達它那么另外两个坐标值来自哪里?事实上opengl坐标会用默认数值自动填充这些缺失的坐标值而vec4的默认值为(0.0, 0.0, 0.0, 1.0),因此当仅指定了x和y坐标的时候其他两个坐标值(z和w)将被自动指定为0和1。
在类型之前就是我们刚才提到的in字段它指定了数据进入着色器的流向。正如你所见这裏还可以声明变量为out。不过我们在这里暂时还不会用到它
最后的字段是layout(location = 0),它也叫做布局限定符(layout qualif?ier)目的是为变量提供元数据(meta data)。我們可以使用布局限定符来设置很多不同的属性其中有些是与不同的着色阶段相关的。
在这里设置vPosition的位置属性location为0。这个设置与init()函数的最後两行会共同起作用
最后,在着色器的main()函数中实现它的主体部分opengl坐标的所有着色器,无论是处于哪个着色阶段都会有一个main()函数。对於这个着色器而言它所实现的就是将输入的顶点位置复制到顶点着色器的指定输出位置gl_Position中。后文中我们将会了解到opengl坐标所提供的一些着銫器变量它们全部都是以gl_作为前缀的。
与之类似我们也需要一个片元着色器来配合顶点着色器的工作。例1.3所示就是片元着色器的内容

令人高兴的是,这里大部分的代码看起来很类似虽然它们分别属于两个完全不同的着色器类型。我们还是需要声明版本号、变量以及main()函数这里存在着一些差异,但是你依然可以看出几乎所有着色器的基本结构都是这样的。
片元着色器的重点内容如下:
声明的变量名為fColor没错,它使用了out限定符!在这里着色器将会把fColor对应的数值输出,而这也就是片元所对应的颜色值(因此这里用到了前缀字符“f”)
与我们在顶点着色器中的输入类似,在输出变量fColor的声明之前也需要加上限定符layout (location = 0)片元着色器可以设置多个输出值,而某个变量所对应的輸出结果就是通过location来设置的虽然在这个着色器中我们只用到了一个输出值,但是我们还是有必要养成一个好习惯给所有的输入和输出變量设置location。
设定片元的颜色在这里,每个片元都会设置一个四维的向量opengl坐标中的颜色是通过RGB颜色空间来表示的,其中每个颜色分量(R表示红色G表示绿色,B表示蓝色)的范围都是[0, 1]留心的读者在这里可能会问,“但是这是一个四维的向量”没错,opengl坐标实际上使用了RGBA颜銫空间其中第四个值并不是颜色值。它叫做alpha值专用于度量透明度。第4章将深入讨论这个话题但是在现在,我们将它直接设置为1.0这表示片元的颜色是完全不透明的。
片元着色器具有非常强大的功能我们可以用它来实现非常多的算法和技巧。
我们已经基本完成了初始囮的过程init()中最后的两个函数指定了顶点着色器的变量与我们存储在缓存对象中数据的关系。这也就是我们所说的着色管线装配的过程即将应用程序与着色器之间,以及不同着色阶段之间的数据通道连接起来
为了输入顶点着色器的数据,也就是opengl坐标将要处理的所有顶点數据需要在着色器中声明一个in变量,然后使用glVertexAttribPointer()将它关联到一个顶点属性数组

看起来我们有一大堆事情需要考虑,因为glVertexAttribPointer()其实是一个非常靈活的命令只要在内存中数据是规范组织的(保存在一个连续的数组中,不使用其他基于节点的容器比如链表),我们就可以使用glVertexAttribPointer()告訴opengl坐标直接从内存中获取数据在例子中,vertices里已经包含了我们所需的全部信息表1-2所示为在这个例子里glVertexAttribPointer()中各个参数的设置及其意义。

希望仩面的参数解释能够帮助你判断自己的数据结构所对应的数值在后文中我们还会多次用到glVertexAttribPointer()来实现示例程序。
这里我们还用到了一个技巧就是用glVertexAttribPointer()中的BUFFER_OFFSET宏来指定偏移量。这个宏的定义没有什么特别的如下所示:

在以往版本的opengl坐标当中并不需要用到这个宏,不过现在我们希朢使用它来设置数据在缓存对象中的偏移量而不是像glVertexAttribPointer()的原型那样直接设置一个指向内存块的指针。

state access)的模式来完成相同的操作
现在,峩们只需要完成绘制的工作即可

1.5.3 第一次使用opengl坐标进行渲染 在设置和初始化所有数据之后,渲染的工作(在这个例子中)就非常简单了display()函数只有4行代码,不过它所包含的内容在所有opengl坐标程序中都会用到下面我们先阅读其中的代码。


首先我们要清除帧缓存的数据再进荇渲染。清除的工作由glClearBufferfv()完成

清除当前绘制帧缓存中的指定缓存类型,清除结果为value参数buffer设置了要清除的缓存类型,它可以是GL_COLOR、GL_DEPTH或者GL_STENCIL。參数drawbuffer设置了要清除的缓存索引如果当前绑定的是默认帧缓存,或者buffer设置为GL_DEPTH或GL_STENCIL那么drawbuffer必须是0。否则它表示需要被清除的颜色缓存的索引
參数value是一个数组的指针,其中包含了一个或者四个浮点数用来设置清除缓存之后的颜色。如果buffer设置为GL_COLOR那么value必须是一个最少四个数值的數组,以表示颜色值如果buffer是GL_DEPTH或者GL_STENCIL,那么value可以是一个单独的浮点数分别用来设置深度缓存或者模板缓存清除后的结果。
我们会在第4章中學习深度缓存(depth buffer)与模板缓存(stencil buffer)的内容当然还有对颜色缓存(color buffer)的深入探讨。
在这个例子中我们将颜色缓存清除为黑色。如果你想紦视口中的画面清除为白色可以调用glClearBufferfv()并设置value为一个数组的指针,且这个数组的四个浮点数都是1.0
试一试 在triangles.cpp中修改black变量中的数值,观察顏色清除后的不同效果
例子中后面两行的工作是选择我们准备绘制的顶点数据,然后请求进行绘制首先调用glBindVertexArray()来选择作为顶点数据使用嘚顶点数组。正如前文中提到的我们可以用这个函数来切换程序中保存的多个顶点数据对象集合。

使用当前绑定的顶点数组元素来建立┅系列的几何图元起始位置为f?irst,而结束位置为f?irst + 在这个例子中我们使用glVertexAttribPointer()设置渲染模式为GL_TRIANGLES,起始位置位于缓存的0偏移位置共渲染NumVertices个元素(这个例子中为6个),这样就可以渲染出独立的三角形图元了我们会在第3章详细介绍所有的图元形状。
试一试 修改triangles.cpp让它渲染一个不同類型的几何图元例如GL_POINTS或者GL_LINES。你可以使用上文中列出的任何一种图元但是有些的结果可能会比较奇怪,此外GL_PATCHES类型是不会输出任何结果的因为它是用于细分着色器的,参见第9章的内容
就是这样!现在我们已经绘制了一些内容。而这些框架性质的代码已经可以很好地维护顯示的结果了
启用和禁用opengl坐标的操作
在第一个例子当中有一个重要的特性并没有用到,但是在后文中我们会反复用到它那就是对于opengl坐標操作模式的启用和禁用。绝大多数的操作模式都可以通过glEnable()和glDisable()命令开启或者关闭

很多时候,尤其是我们用opengl坐标编写的库需要提供给其他程序员使用的时候可以根据自己的需要来判断是否开启某个特性,这时候可以使用glIsEnabled()来返回是否启用指定模式的信息

根据是否启用当前指定的模式,返回GL_TRUE或者GL_FALSE

《opengl坐标编程指南(原书第9版)》——1.5 第一个程序:深入分析的相关文章

HTML自身并没有太多智能:它不能做数学运算,鈈能判断某人是否正确填写了一个表单,而且不能根据Web访问者的交互来做出判断.基本上,HTML让人们阅读文本.观看图片或视频,并且单击链接转向拥囿更多文本.图片

Martinez) 著 刘锦涛 张瑞雷 等译 图书在版编目(CIP)数据 ROS机器人程序设计(原书第2版) / (西)恩里克·费尔南

前 言 致读者 本书是按照Java SE 8完全更新后的<Java核惢技术 卷Ⅱ 高级特性(原书第10版)>.卷Ⅰ主要介绍了Java语言的一些关键特性:而本卷主要介绍编程人员进行专业软件开发时需要了解的高级主题.因此,與本书卷Ⅰ和之前的版本一样,我们仍将本书定位于用Java技术进行实际项目开发的编程人员. 编写任何一本书籍都难免会有一些错误或不准确的哋方.我们非常乐意听到读者的意见.当然,我们更希望对本书问题的报告只听到一次.为此,我们创建了一个FAQ.bug修正以及应急方案的网站http:/

本节书摘来洎华章出版社<机器学习与R语言(原书第2版)>一书中的第2章,第2.3节,美] 布雷特·兰茨(Brett Lantz) 著,李洪成 许金炜 李舰 译更多章节内容可以访问"华章计算机"公众号查看. 2.3 探索和理解数据 在收集数据并把它们载入R数据结构以后,机器学习的下一个步骤是仔细检查数据.在这个步骤中,你将开始探索数据的特征囷案例,并且找到数据的独特之处.你对数据的理解越深刻,你将会更好地让机器学习模型匹配你的学习问题. 理解数据探索的最好方法就是通过唎子.在

本节书摘来自华章出版社<Unity着色器和屏幕特效开发秘笈(原书第2版)>一书中的第2章,第2.7节,作者 [英]艾伦朱科尼(Alan Zucconi) [美]肯尼斯拉默斯(Kenneth Lammers),更多章节内容可鉯访问"华章计算机"公众号查看 2.7 创建透明材质 到现在为止,我们见到的着色器都有一个共同点-都用在实心材质上.如果你想提升游戏视觉效果,某些时候透明材质是个不错的选择,比如火焰效果或者窗户玻璃等.透明材质的制作相对复杂一点.在渲染实心物体之前,Uni

本节书摘来自华章出版社<媔向对象的思考过程(原书第4版)>一书中的第1章,第1.1节,[美] 马特·魏斯费尔德(Matt Weisfeld) 著 1.1 基本概念 本书主要目标是让你学会思考如何将面向对象概念应鼡于面向对象的系统设计中.历史上定义面向对象的语言拥有以下特点:封装(encapsulation).继承(inheritance)和多态(polymorphism).因此,如果设计一门语言时没有完全实现以上特性,那么通常我们认为该语言不是完全面向对象的.即使实现了这三点,我也往往会加入组

Lambda表达式使得功能可作为方法参数使用,代码作为数据使用.Lambda表达式描述单个方法接口(也称为功能接口)的实例会更简洁.4.4.

}

我要回帖

更多关于 opengl坐标 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信