Skip to content

Commit 428cb4e

Browse files
committed
update
1 parent c9b2e71 commit 428cb4e

4 files changed

Lines changed: 111 additions & 3 deletions

File tree

VideoDevelopment/OpenGL/1.OpenGL简介.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,20 @@ GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo.get(0));
366366
```
367367
从调用glBindBuffer()这一刻起,我们使用的任何(在GL_ARRAY_BUFFER目标上的)缓冲调用都会用来配置当前绑定的缓冲(VBO)。
368368
然后我们可以调用glBufferData()函数,它会把之前定义的顶点数据复制到缓冲的内存中(小助理把对应的数据单独记录下来了)。
369-
369+
370+
371+
372+
绑定对象的过程有点类似设置铁路的道岔开关。
373+
一旦设置了开关,从这条线路通过的所有列车都会驶向对应的轨道。
374+
如果我们将开关设置到另一个状态,那么所有之后经过的列车都会驶向另一条轨道。OpenGL的对象也是如此。
375+
376+
总体上来说,在两种情况下我们需要绑定一个对象:
377+
- 创建对象并初始化它所对应的数据是。
378+
- 每次我们准备使用这个对象,而它并不是当前绑定的对象时。
379+
380+
381+
382+
370383
```C
371384
// glBufferData creates a new data store for the buffer object currently bound to target.
372385
// glBufferData为当前绑定到的目标缓冲区对象创建一个新的数据存储

VideoDevelopment/OpenGL/7.OpenGL ES着色器语言GLSL.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ precision mediump int;
174174

175175
#### Uniform
176176

177+
Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同:
178+
179+
- uniform是全局的(Global)。全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。
180+
181+
- 无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。
182+
183+
177184
CPU在处理并行线程的时候,每个线程负责给完整图像的一部分配置颜色。
178185
尽管每个线程和其他线程之间不能有数据交换,但我们能从CPU给每个线程输入数据。
179186
因为显卡的架构,所有线程的输入值必须统一(uniform),而且必须设为只读。

VideoDevelopment/OpenGL/8.GLES类及Matrix类.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,70 @@ GLES30.glVertexAttribPointer(1, 4, GLES30.GL_FLOAT, false, 0, colorBuffer);
138138

139139
如果启用,那么当GLES30.glDrawArrays或者GLES30.glDrawElements被调用时,顶点属性数组会被使用。
140140

141+
142+
143+
144+
尽管现在已经知道了如何创建一个物体、着色、加入纹理,给它们一些细节的表现,但因为它们都还是静态的物体,仍不够有趣。
145+
146+
我们可以尝试着在每一帧改变物体的顶点并且重配置缓冲区从而使它移动,但这太繁琐了,而且会消耗很多的处理时间。
147+
我们现在有一个更好的解决方案,使用(多个)矩阵(Matrix)对象可以更好的变换(Transform)一个物体。
148+
149+
为了更好的了解矩阵,需要先了解向量.
150+
151+
## 向量
152+
153+
向量有一个方向(Direction)和大小(Magnitude,也叫强度或长度)。
154+
155+
你可以把向量想象成一个藏宝图上的指示: 向左走10步,向北走3步,然后向右走5步。
156+
157+
这里面左就是方向,10步就是向量的长度。
158+
159+
向量可以在任何维度(Dimension)上,但是我们通常只使用2至4维。
160+
如果一个向量有2个维度,它表示一个平面的方向(想象一下2D的图像)。
161+
当它有3个维度的时候它可以表达一个3D世界的方向。
162+
163+
164+
165+
![image](https://github.com/CharonChui/Pictures/blob/master/glsl_vector_0.png?raw=true)
166+
167+
上图中有3个向量,每个向量在2D图像中都用一个箭头(x, y)表示。
168+
***由于向量表示的是方向,起始于何处并不会改变它的值。***
169+
例如上面的向量v和w是相等的,尽管他们的起始点不同。
170+
171+
172+
由于向量是一个方向,所以有些时候会很难形象的将它们用位置(Position)表示出来。
173+
为了让其更为直观,我们通常设定这个方向的原点为(0, 0, 0),然后指定一个方向,对应一个点,使其变为位置向量(Position Vector)。
174+
你也可以把起点设置为其他的点,然后说这个向量从这个点起始指向另一个点。
175+
176+
比如说位置向量(3, 5)在图像中的起点会是(0, 0),并会指向(3, 5)。我们可以使用向量在2D或3D空间中表示方向与位置。
177+
178+
179+
### 向量相乘
180+
181+
两个向量相乘是一种很奇怪的情况。
182+
普通的乘法在向量上是没有定义的,因为它在视觉上是没有意义的。
183+
184+
但是在相乘的时候我们有两种特定情况可以选择:
185+
186+
- 一个是点乘(Dot Product)
187+
- 一个是叉乘(Cross Product)
188+
189+
190+
##### 点乘
191+
192+
两个向量的点乘等于它们的数乘结果乘以两个向量之间夹角的余弦值。
193+
194+
##### 叉乘
195+
196+
叉乘只在3D空间中有定义,它需要两个不平行向量作为输入,生成一个正交于两个输入向量的第三个向量。
197+
如果输入的两个向量也是正交的,那么叉乘之后将会产生3个相互正交的向量。
198+
下面的图就是3D控件中叉乘的样子:
199+
200+
![image](https://github.com/CharonChui/Pictures/blob/master/opengl_chacheng.png?raw=true)
201+
202+
203+
204+
141205
## Matrix
142206

143207
Matrix就是专门设计出来帮助我们简化矩阵和向量运算操作的,里面所有的实现原理都是线性代数中的运算。

VideoDevelopment/OpenGL/9.OpenGL ES纹理.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
那么在 OpenGLES 中,***纹理实际上是一个可以被采样的复杂数据集合,是 GPU 的图像数据结构,纹理分为 2D 纹理、 立方图纹理和 3D 纹理。***
1313

14-
2D 纹理是 OpenGLES 中最常用和最常见的纹理形式,是一个图像数据的二维数组。纹理中的一个单独数据元素称为纹素或纹理像素。
14+
***2D 纹理是 OpenGLES 中最常用和最常见的纹理形式,是一个图像数据的二维数组。纹理中的一个单独数据元素称为纹素或纹理像素。***
1515

1616
立方图纹理是一个由 6 个单独的 2D 纹理面组成的纹理。立方图纹理像素的读取通过使用一个三维坐标(s,t,r)作为纹理坐标。
1717

@@ -129,9 +129,29 @@ OpenGL不能直接加载jpg或者png这类被编码的压缩格式,需要加
129129

130130
### 纹理过滤
131131

132+
纹理坐标不依赖于分辨率,它可以是任意浮点值,所以OpenGL需要知道怎样将纹理像素映射到纹理坐标。
133+
134+
当你有一个很大的物体但是纹理的分辨率很低的时候这就变得很重要了。
135+
136+
132137
当我们通过光栅化将图形处理成一个个小片段的时候,再将纹理采样,渲染到指定位置上时,通常会遇到纹理元素和小片段并非一一对应。
133138
这时候,会出现纹理的压缩或者放大。那么在这两种情况下,就会有不同的处理方案,这就是纹理过滤了。
134139

140+
141+
纹理过滤有很多选项,这里只说最重要的两项: GL_NEAREST和GL_LINEAR。
142+
143+
- GL_NEAREST: 临近过滤,是OpenGL默认的纹理过滤方式,会选择中心点最接近纹理坐标的那个像素。
144+
145+
- GL_LINEAR: 线性过滤,会基于纹理坐标附近的纹理像素,计算出一个插值,近似出这些纹理像素之间的颜色。一个纹理像素的中心距离纹理坐标越近,那么这个纹理像素的颜色对最终的样本颜色的贡献越大。
146+
147+
148+
149+
如果在一个很大的物体上应用一张低分辨率的纹理会发生什么呢(纹理被放大了,每个纹理像素都能看到)?
150+
151+
GL_NEAREST产生了颗粒状的图案,我们能够清晰看到组成纹理的像素。
152+
而GL_LINEAR能够产生更平滑的图案,很难看出单个的纹理像素。GL_LINEAR可以产生更真实的输出。
153+
154+
135155
### 纹理对象和纹理的加载
136156

137157
纹理应用的第一步是创建一个纹理对象。纹理对象是一个容器对象,保存渲染所需的纹理数据,例如图像数据、过滤模式和包装模式。
@@ -352,7 +372,7 @@ color = texture(samp, tc);
352372
纹理的绘制:
353373

354374
```java
355-
//激活纹理,设置当前活动的纹理单元为单元0
375+
//激活纹理单元,设置当前活动的纹理单元为单元0
356376
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
357377
//绑定纹理,将纹理id绑定到当前活动的纹理单元上
358378
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
@@ -365,6 +385,10 @@ GLES20.glUniform1i(aTextureLocation, 0);
365385
通过纹理单元赋值给采样器,我们可以一次绑定多个纹理,只要我们在使用的时候激活纹理。
366386

367387

388+
OpenGL至少保证有16个纹理单元供你使用,也就是说你可以激活从GL_TEXTURE0到GL_TEXTURE15。
389+
它们都是按顺序定义的,所以我们也可以通过GL_TEXUTURE0 + 8的方式获得GL_TEXTURE8,这在需要循环一些纹理单元的时候会很有用。
390+
391+
368392
```java
369393
public class TextureRender extends BaseGLSurfaceViewRenderer {
370394
private final FloatBuffer vertextBuffer;

0 commit comments

Comments
 (0)