1
0
mirror of https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git synced 2025-08-23 20:55:27 +08:00

Fix all the titles

This commit is contained in:
Meow J
2016-07-06 01:39:55 +08:00
parent fd614ffcc4
commit 86dc92e4db
45 changed files with 508 additions and 527 deletions

View File

@@ -9,21 +9,19 @@
这章不会向你展示什么新的功能也不会对你的场景的视觉效果有较大提升。本文多多少少地深入探讨了一些GLSL有趣的知识它们可能在将来能帮助你。基本来说有些不可不知的内容和功能在你去使用GLSL创建OpenGL应用的时候能让你的生活更轻松。
我们会讨论一些内建变量、组织着色器输入和输出的新方式以及一个叫做uniform缓冲对象的非常有用的工具。
我们会讨论一些内建变量(Built-in Variable)、组织着色器输入和输出的新方式以及一个叫做uniform缓冲对象(Uniform Buffer Object)的非常有用的工具。
## GLSL的内建变量
# GLSL的内建变量
着色器是很小的如果我们需要从当前着色器以外的别的资源里的数据那么我们就不得不传给它。我们学过了使用顶点属性、uniform和采样器可以实现这个目标。GLSL有几个以**gl\_**为前缀的变量,使我们有一个额外的手段来获取和写入数据。其中两个我们已经打过交道了:`gl_Position``gl_FragCoord`,前一个是顶点着色器的输出向量,后一个是片段着色器的变量。
我们会讨论几个有趣的GLSL内建变量并向你解释为什么它们对我们来说很有好处。注意我们不会讨论到GLSL中所有的内建变量因此如果你想看到所有的内建变量还是最好去查看[OpenGL的wiki](http://www.opengl.org/wiki/Built-in_Variable_(GLSL)。
### 顶点着色器变量
#### gl_Position
## 顶点着色器变量
我们已经了解`gl_Position`是顶点着色器裁切空间输出的位置向量。如果你想让屏幕上渲染出东西`gl_Position`必须使用。否则我们什么都看不到。
#### gl_PointSize
### gl_PointSize
我们可以使用的另一个可用于渲染的基本图形(primitive)是**GL\_POINTS**,使用它每个顶点作为一个基本图形,被渲染为一个点(point)。可以使用`glPointSize`函数来设置这个点的大小,但我们还可以在顶点着色器里修改点的大小。
@@ -51,7 +49,7 @@ void main()
想象一下,每个顶点表示出来的点的大小的不同,如果用在像粒子生成之类的技术里会挺有意思的。
#### gl_VertexID
### gl_VertexID
`gl_Position`和`gl_PointSize`都是输出变量,因为它们的值是作为顶点着色器的输出被读取的;我们可以向它们写入数据来影响结果。顶点着色器为我们提供了一个有趣的输入变量,我们只能从它那里读取,这个变量叫做`gl_VertexID`。
@@ -59,11 +57,11 @@ void main()
尽管目前看似没用,但是我们最好知道我们能获取这样的信息。
### 片段着色器的变量
## 片段着色器的变量
在片段着色器中也有一些有趣的变量。GLSL给我们提供了两个有意思的输入变量它们是`gl_FragCoord`和`gl_FrontFacing`。
#### gl_FragCoord
### gl_FragCoord
在讨论深度测试的时候,我们已经看过`gl_FragCoord`好几次了,因为`gl_FragCoord`向量的z元素和特定的fragment的深度值相等。然而我们也可以使用这个向量的x和y元素来实现一些有趣的效果。
@@ -88,9 +86,7 @@ void main()
我们现在可以计算出两个完全不同的片段着色器结果,每个显示在窗口的一端。这对于测试不同的光照技术很有好处。
#### gl_FrontFacing
### gl_FrontFacing
片段着色器另一个有意思的输入变量是`gl_FrontFacing`变量。在面剔除教程中我们提到过OpenGL可以根据顶点绘制顺序弄清楚一个面是正面还是背面。如果我们不适用面剔除那么`gl_FrontFacing`变量能告诉我们当前片段是某个正面的一部分还是背面的一部分。然后我们可以决定做一些事情,比如为正面计算出不同的颜色。
@@ -119,7 +115,7 @@ void main()
注意,如果你开启了面剔除,你就看不到箱子里面有任何东西了,所以此时使用`gl_FrontFacing`毫无意义。
#### gl_FragDepth
### gl_FragDepth
输入变量`gl_FragCoord`让我们可以读得当前片段的窗口空间坐标和深度值但是它是只读的。我们不能影响到这个片段的窗口屏幕坐标但是可以设置这个像素的深度值。GLSL给我们提供了一个叫做`gl_FragDepth`的变量,我们可以用它在着色器中遂舍之像素的深度值。
@@ -168,11 +164,11 @@ void main()
## 接口块(Interface blocks)
# 接口块
到目前位置,每次我们打算从顶点向片段着色器发送数据,我们都会声明一个相互匹配的输出/输入变量。从一个着色器向另一个着色器发送数据,一次将它们声明好是最简单的方式,但是随着应用变得越来越大,你也许会打算发送的不仅仅是变量,最好还可以包括数组和结构体。
为了帮助我们组织这些变量GLSL为我们提供了一些叫做接口块(Interface blocks)的东西好让我们能够组织这些变量。声明接口块和声明struct有点像不同之处是它现在基于块block使用in和out关键字来声明最后它将成为一个输入或输出块block
为了帮助我们组织这些变量GLSL为我们提供了一些叫做接口块(Interface Blocks)的东西好让我们能够组织这些变量。声明接口块和声明struct有点像不同之处是它现在基于块block使用in和out关键字来声明最后它将成为一个输入或输出块block
```c++
#version 330 core
@@ -218,11 +214,11 @@ void main()
如果两个interface block名一致它们对应的输入和输出就会匹配起来。这是另一个可以帮助我们组织代码的有用功能特别是在跨着色阶段的情况比如几何着色器。
## uniform缓冲对象 (Uniform buffer objects)
# Uniform缓冲对象
我们使用OpenGL很长时间了也学到了一些很酷的技巧但是产生了一些烦恼。比如说当时用一个以上的着色器的时候我们必须一次次设置uniform变量尽管对于每个着色器来说它们都是一样的所以为什么还麻烦地多次设置它们呢
OpenGL为我们提供了一个叫做uniform缓冲对象的工具使我们能够声明一系列的全局uniform变量 它们会在几个着色器程序中保持一致。当时用uniform缓冲的对象时相关的uniform只能设置一次。我们仍需为每个着色器手工设置唯一的uniform。创建和配置一个uniform缓冲对象需要费点功夫。
OpenGL为我们提供了一个叫做uniform缓冲对象(Uniform Buffer Object)的工具使我们能够声明一系列的全局uniform变量 它们会在几个着色器程序中保持一致。当时用uniform缓冲的对象时相关的uniform只能设置一次。我们仍需为每个着色器手工设置唯一的uniform。创建和配置一个uniform缓冲对象需要费点功夫。
因为uniform缓冲对象是一个缓冲因此我们可以使用`glGenBuffers`创建一个,然后绑定到`GL_UNIFORM_BUFFER`缓冲目标上然后把所有相关uniform数据存入缓冲。有一些原则像uniform缓冲对象如何储存数据我们会在稍后讨论。首先我们我们在一个简单的顶点着色器中用uniform块(uniform block)储存投影和视图矩阵:
@@ -252,7 +248,7 @@ void main()
### uniform块布局(uniform block layout)
## Uniform块布局
一个uniform块的内容被储存到一个缓冲对象中实际上就是在一块内存中。因为这块内存也不清楚它保存着什么类型的数据我们就必须告诉OpenGL哪一块内存对应着色器中哪一个uniform变量。
@@ -312,7 +308,7 @@ layout (std140) uniform ExampleBlock
在定义uniform块前面添加layout (std140)声明我们就能告诉OpenGL这个uniform块使用了std140布局。另外还有两种其他的布局可以选择它们需要我们在填充缓冲之前查询每个偏移量。我们已经了解了分享布局shared layout和其他的布局都将被封装packed。当使用封装packed布局的时候不能保证布局在别的程序中能够保持一致因为它允许编译器从uniform块中优化出去uniform变量这在每个着色器中都可能不同。
### 使用uniform缓冲
## 使用uniform缓冲
我们讨论了uniform块在着色器中的定义和如何定义它们的内存布局但是我们还没有讨论如何使用它们。
@@ -371,7 +367,7 @@ glBindBuffer(GL_UNIFORM_BUFFER, 0);
同样的处理也能够应用到uniform块中其他uniform变量上。
### 一个简单的例子
## 一个简单的例子
我们来师范一个真实的使用uniform缓冲对象的例子。如果我们回头看看前面所有演示的代码我们一直使用了3个矩阵投影、视图和模型矩阵。所有这些矩阵中只有模型矩阵是频繁变化的。如果我们有多个着色器使用了这些矩阵我们可能最好还是使用uniform缓冲对象。