mirror of
https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git
synced 2025-08-22 20:25:28 +08:00
fix some translation errors and code displaying errors.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
---|---
|
||||
作者 | JoeyDeVries
|
||||
翻译 | [Django](http://bullteacher.com/)
|
||||
校对 | [Geequlim](http://geequlim.com)
|
||||
校对 | [Geequlim](http://geequlim.com), [KenLee](https://hellokenlee.github.io/)
|
||||
|
||||
|
||||
这章不会向你展示什么新的功能,也不会对你的场景的视觉效果有较大提升。本文多多少少地深入探讨了一些GLSL有趣的知识,它们可能在将来能帮助你。基本来说有些不可不知的内容和功能在你去使用GLSL创建OpenGL应用的时候能让你的生活更轻松。
|
||||
@@ -306,7 +306,7 @@ layout (std140) uniform ExampleBlock
|
||||
|
||||
尝试自己计算出偏移量,把它们和表格对比,你可以把这件事当作一个练习。使用计算出来的偏移量,根据std140布局规则,我们可以用`glBufferSubData`这样的函数,使用变量数据填充缓冲。虽然不是很高效,但std140布局可以保证在每个程序中声明的这个uniform块的布局保持一致。
|
||||
|
||||
在定义uniform块前面添加layout (std140)声明,我们就能告诉OpenGL这个uniform块使用了std140布局。另外还有两种其他的布局可以选择,它们需要我们在填充缓冲之前查询每个偏移量。我们已经了解了分享布局(shared layout)和其他的布局都将被封装(packed)。当使用封装(packed)布局的时候,不能保证布局在别的程序中能够保持一致,因为它允许编译器从uniform块中优化出去uniform变量,这在每个着色器中都可能不同。
|
||||
在定义uniform 块前面添加`layout (std140)`的声明表示这个uniform块使用 std140 布局。 另外我们还有两种布局可以选择,但是这两种布局都要求我们在填充缓冲之前查询每一个变量的偏移。 我们已经介绍了** 共享布局(shared layout) **,剩下另一种布局则是 ** 封装布局(packed layout) **。当我们使用封装布局(pack layout)的时候, OpenGL不保证所有程序的数据布局方式是一样的(也就是不共享),因为该布局允许编译器去优化uniform变量的数据放置方式,而这种优化的结果因不同的Shader而异。
|
||||
|
||||
## 使用uniform缓冲
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
---|---
|
||||
作者 | JoeyDeVries
|
||||
翻译 | [Django](http://bullteacher.com/)
|
||||
校对 | [Geequlim](http://geequlim.com)
|
||||
校对 | [Geequlim](http://geequlim.com), [KenLee](https://hellokenlee.github.io/)
|
||||
|
||||
在顶点和片段着色器之间有一个可选的着色器,叫做几何着色器(Geometry Shader)。几何着色器以一个或多个表示为一个单独基本图形(primitive)的顶点作为输入,比如可以是一个点或者三角形。几何着色器在将这些顶点发送到下一个着色阶段之前,可以将这些顶点转变为它认为合适的内容。几何着色器有意思的地方在于它可以把(一个或多个)顶点转变为完全不同的基本图形(primitive),从而生成比原来多得多的顶点。
|
||||
|
||||
@@ -337,15 +337,15 @@ EndPrimitive();
|
||||
|
||||
# 爆破物体
|
||||
|
||||
绘制房子的确很有趣,但我们不会经常这么用。这就是为什么现在我们将撬起物体缺口,形成爆炸式物体的原因!虽然这个我们也不会经常用到,但是它能向你展示一些几何着色器的强大之处。
|
||||
尽管绘制房子的确很有趣,但我们不会经常这么做。因此我们接下来要更上一层楼,去爆破物体啦!虽然这个我们可能也不会经常用到,但是它能向你展示一些几何着色器的强大之处。
|
||||
|
||||
当我们说对一个物体进行爆破(Explode)的时候并不是说我们将要把之前的那堆顶点炸掉,但是我们打算把每个三角形沿着它们的法线向量移动一小段距离。效果是整个物体上的三角形看起来就像沿着它们的法线向量爆炸了一样。纳米服上的三角形的爆炸式效果看起来是这样的:
|
||||
当我们说对一个物体进行爆破(Explode)的时候并不是说我们将要把之前的那堆顶点炸掉,但是我们打算把每个三角形沿着它们的法线向量移动一小段距离。视觉效果是整个物体上的三角形看起来就像沿着它们的法线向量爆炸了一样。纳米服上的三角形的爆炸式效果看起来是这样的:
|
||||
|
||||

|
||||
|
||||
这样一个几何着色器效果的一大好处是,它可以用到任何物体上,无论它们多复杂。
|
||||
|
||||
因为我们打算沿着三角形的法线向量移动三角形的每个顶点,我们需要先计算它的法线向量。我们要做的是计算出一个向量,它垂直于三角形的表面,使用这三个我们已经的到的顶点就能做到。你可能记得变换教程中,我们可以使用叉乘获取一个垂直于两个其他向量的向量。如果我们有两个向量a和b,它们平行于三角形的表面,我们就可以对这两个向量进行叉乘得到法线向量了。下面的几何着色器函数做的正是这件事,它使用3个输入顶点坐标获取法线向量:
|
||||
因为我们打算沿着三角形的法线向量移动三角形的每个顶点,我们需要先计算它的法线向量。我们要做的是计算出一个向量,它垂直于三角形的表面,使用这三个我们已经的到的顶点就能做到。你可能记得在变换教程中,我们可以使用 **叉乘**获取一个垂直于两个其他向量的向量。如果我们有两个向量a和b,它们平行于三角形的表面,我们就可以对这两个向量进行叉乘得到法线向量了。下面的几何着色器函数做的正是这件事,它使用3个输入顶点坐标获取法线向量:
|
||||
|
||||
```c++
|
||||
vec3 GetNormal()
|
||||
@@ -412,15 +412,15 @@ void main() {
|
||||
|
||||
```c++
|
||||
glUniform1f(glGetUniformLocation(shader.Program, "time"), glfwGetTime());
|
||||
```
|
||||
```
|
||||
|
||||
最后的结果是一个随着时间持续不断地爆炸的3D模型(不断爆炸不断回到正常状态)。尽管没什么大用处,它却向你展示出很多几何着色器的高级用法。你可以用[完整的源码](http://learnopengl.com/code_viewer.php?code=advanced/geometry_shader_explode)和[着色器](http://learnopengl.com/code_viewer.php?code=advanced/geometry_shader_explode_shaders)对比一下你自己的。
|
||||
|
||||
# 显示法向量
|
||||
|
||||
在这部分我们将使用几何着色器写一个例子,非常有用:显示一个法线向量。当编写光照着色器的时候,你最终会遇到奇怪的视频输出问题,你很难决定是什么导致了这个问题。通常导致光照错误的是,不正确的加载顶点数据,以及给它们指定了不合理的顶点属性,又或是在着色器中不合理的管理,导致产生了不正确的法线向量。我们所希望的是有某种方式可以检测出法线向量是否正确。把法线向量显示出来正是这样一种方法,恰好几何着色器能够完美地达成这个目的。
|
||||
在这部分我们将使用几何着色器写一个非常有用的例子:绘制出任意一个物体的全部法向量。当编写光照着色器的时候,你可能会得到一些奇怪的渲染输出,但是你却又很难判断是什么导致了这个问题。通常导致光照错误的是,由不正确地加载顶点数据或者错误地定义定点属性又或者在着色器中错误地处理等原因导致的法向量错误。我们希望有某种方式可以检测出我们使用法向量是否正确。一种比较好的方法去检测我们的法向量是否有错误是直接把物体的法向量全部绘制出来,而恰恰好几何着色器能完美地达成这个目标。
|
||||
|
||||
思路是这样的:我们先不用几何着色器,正常绘制场景,然后我们再次绘制一遍场景,但这次只显示我们通过几何着色器生成的法线向量。几何着色器把一个三角形基本图形作为输入类型,用它们生成3条和法线向量同向的线段,每个顶点一条。伪代码应该是这样的:
|
||||
思路是这样的:我们先不用几何着色器,正常绘制场景。然后我们再次绘制一遍场景,但这次只显示我们通过几何着色器生成的法线向量。几何着色器把一个三角形基本图形作为输入类型,用它们生成3条沿法向量方向的法线——每个顶点一条。伪代码应该类似这个样子:
|
||||
|
||||
```c++
|
||||
shader.Use();
|
||||
@@ -429,7 +429,7 @@ normalDisplayShader.Use();
|
||||
DrawScene();
|
||||
```
|
||||
|
||||
这次我们会创建一个使用模型提供的顶点法线,而不是自己去生成。为了适应缩放和旋转我们会在把它变换到裁切空间坐标前,使用法线矩阵来法线(几何着色器用他的位置向量做为裁切空间坐标,所以我们还要把法线向量变换到同一个空间)。这些都能在顶点着色器中完成:
|
||||
这次我们会在几何着色器中使用模型提供的顶点法线,而不用自己去生成。为了适应(由于 view 和 model 矩阵产生的)缩放和旋转,我们会在把法向量变换到裁切空间坐标系(clip-space)前,先把它变成法向量矩阵(几何着色器接受在裁切空间坐标系下的位置向量,因此我们也需要把法向量转换到同一空间坐标系下)。这些步骤都能在顶点着色器中完成:
|
||||
|
||||
```c++
|
||||
#version 330 core
|
||||
@@ -452,7 +452,7 @@ void main()
|
||||
}
|
||||
```
|
||||
|
||||
经过变换的裁切空间法线向量接着通过一个接口块被传递到下个着色阶段。几何着色器接收每个顶点(带有位置和法线向量),从每个位置向量绘制出一个法线向量:
|
||||
经过变换的裁切坐标系空间法向量通过一个接口块被传递到下个着色阶段。几何着色器接收每个顶点的信息(包括其位置向量和法向量),从每个定点的位置上沿法向量方向画一条法线:
|
||||
|
||||
```c++
|
||||
#version 330 core
|
||||
@@ -496,10 +496,10 @@ void main()
|
||||
}
|
||||
```
|
||||
|
||||
现在先使用普通着色器来渲染你的模型,然后使用特制的法线可视着色器,你会看到这样的效果:
|
||||
现在先使用普通着色器来渲染你的模型,然后使用特制的法线可视化着色器,你会看到类似这样的效果:
|
||||
|
||||

|
||||
|
||||
除了我们的纳米服现在看起来有点像一个带着隔热手套的全身多毛的家伙外,它给了我们一种非常有效的检查一个模型的法线向量是否有错误的方式。你可以想象下这样的几何着色器也经常能被用在给物体添加毛发上。
|
||||
除了我们的纳米服现在看起来有点像一个带着隔热手套的全身多毛的家伙外,我们拥有了一种非常有效的检查一个模型的法线向量是否有错误的方式。你可以想象到这样的几何着色器也能被用在给物体添加毛发上。
|
||||
|
||||
你可以从这里找到[源码](http://learnopengl.com/code_viewer.php?code=advanced/geometry_shader_normals)和可显示法线的[着色器](http://learnopengl.com/code_viewer.php?code=advanced/geometry_shader_normals_shaders)。
|
||||
|
Reference in New Issue
Block a user