Skip to content

Commit 6521d4f

Browse files
committed
add notes
1 parent 973889f commit 6521d4f

File tree

5 files changed

+162
-23
lines changed

5 files changed

+162
-23
lines changed

VideoDevelopment/OpenGL/1.OpenGL简介.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
## 1.OpenGL简介
22

3+
最近想要在播放器上做一个效果,需要用到OpenGL,一直以来也没关注学习过,就想着学习学习。在网上已经有很多文章,这里为什么还要写?主要是因为在学的时候发现那些文章看完后还是雨里雾里的不明白。要不就是不连贯,要不就是各种错误,各种理解的不对,导致我稀里糊涂的,干脆我不看了,买了一本书,看了书之后再去看文章就彻底明白了,所以我想写一个简单的,能从入门开始一步步学习的,能简单的学会,文章里面有一些是从下面写的参考链接中拷贝过来的,也有一些是自己从书上看的。
4+
35
[OpenGL官网](https://www.opengl.org/)
46

57
OpenGL(Open Graphics Library开放图形库)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口。
68

79
OpenGL的前身是硅谷图形功能(SGI)公司为其图形工作站开发的IRIS GL,后来因为IRIS GL的移植性不好,所以在其基础上,开发出了OpenGl。OpenGl一般用于在图形工作站,PC端使用,由于性能各方面原因,在移动端使用OpenGl基本带不动。为此,Khronos公司就为OpenGl提供了一个子集,OpenGl ES(OpenGl for Embedded System)。
810

9-
网上已经有很多文章,这里为什么还要写?主要是因为最近在学的时候发现那些文章看完后还是雨里雾里的不明白。我想写一个简单的,能从入门开始一步步学习的,能简单的学会,文章里面有一些是从下面写的参考链接中拷贝过来的,也有一些是自己从书上看的。
10-
1111

1212
### OpenGL ES
1313

VideoDevelopment/OpenGL/10.GLSurfaceView+MediaPlayer播放视频.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,58 @@
11
## 10.GLSurfaceView+MediaPlayer播放视频
22

3+
### 相机预览
34

5+
1. 在GLSurfaceView.Render中创建一个纹理,再使用该纹理创建一个SurfaceTexture。
6+
2. 使用该SurfaceTexture创建一个Surface传给相机,相机预览数据就会输出到这个纹理上了。
7+
3. 使用GLSurfaceView.Render将该纹理渲染到GLSurfaceView的窗口上。
8+
4. 使用SurfaceTexture的setOnFrameAvailableListener方法给SurfaceTexture添加一个数据帧可用的监听器,在监听器中调用GLSurfaceView的requestRender方法渲染该帧数据,这样相机每次输出一帧数据就可以渲染一次,在GLSurfaceView窗口中就可以看到相机的预览数据了。
49

5-
平时的视频播放都是使用mediaplayer+textureview或者mediaplayer+surfaceview,但是如果我们要对视频进行一些OpenGL的操作,打个比方说我要在视频播放的时候添加一个滤镜,这个时候就需要用都SurfaceTexture了。
10+
- 顶点着色器
11+
12+
```xml
13+
#version 300 es
14+
15+
layout (location = 0) in vec4 a_Position;
16+
layout (location = 1) in vec2 a_texCoord;
17+
18+
out vec2 v_texCoord;
19+
20+
void main()
21+
{
22+
gl_Position = a_Position;
23+
v_texCoord = a_texCoord;
24+
}
25+
```
26+
27+
- 片段着色器
28+
29+
这里需要注意一下,就是做相机预览的话,纹理的类型需要使用samplerExternalOES,而不是之前渲染图片的sampler2D。
30+
31+
```xml
32+
#version 300 es
33+
#extension GL_OES_EGL_image_external_essl3 : require
34+
precision mediump float;
35+
36+
in vec2 v_texCoord;
37+
out vec4 outColor;
38+
uniform samplerExternalOES s_texture;
39+
40+
void main(){
41+
outColor = texture(s_texture, v_texCoord);
42+
}
43+
```
44+
45+
646

747

848

9-
### TextureView+MediaPlayer播放视频
49+
50+
51+
52+
53+
### 视频播放
54+
55+
平时的视频播放都是使用mediaplayer+textureview或者mediaplayer+surfaceview,但是如果我们要对视频进行一些OpenGL的操作,打个比方说我要在视频播放的时候添加一个滤镜,这个时候就需要用都SurfaceTexture了。
1056

1157
```java
1258
public class VideoActivity extends Activity {

VideoDevelopment/OpenGL/11.OpenGL ES滤镜.md

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,46 @@
11
## 11.OpenGL ES滤镜
22

3-
滤镜其实就是利用纹理。
3+
给图像添加滤镜本质就是图片处理,也就是对图片的像素进行计算,简单来说,图像处理的方法可以分为三类:
4+
5+
- 点算:当前像素的处理只和自身的像素值有关,和其他像素无关,比如灰度处理。
6+
- 领域算:当前像素的处理需要和相邻的一定范围内的像素有关,比如高斯模糊。
7+
- 全局算:在全局上对所有像素进行统一变换,比如几何变换。
8+
9+
### 灰色滤镜
10+
11+
和前一篇文章基本一样,只是修改一下片段着色器的代码,原理就是在片段着色器中去处理颜色,让RGB三个通道的颜色取均值:
12+
13+
```
14+
#version 300 es
15+
#extension GL_OES_EGL_image_external_essl3 : require
16+
precision mediump float;
17+
18+
in vec2 v_texCoord;
19+
out vec4 outColor;
20+
uniform samplerExternalOES s_texture;
21+
22+
//灰度滤镜,具体去处理颜色
23+
void grey(inout vec4 color){
24+
float weightMean = color.r * 0.3 + color.g * 0.59 + color.b * 0.11;
25+
color.r = color.g = color.b = weightMean;
26+
}
27+
28+
void main(){
29+
//拿到颜色值
30+
vec4 tmpColor = texture(s_texture, v_texCoord);
31+
//对颜色值进行处理
32+
grey(tmpColor);
33+
//将处理后的颜色值输出到颜色缓冲区
34+
outColor = tmpColor;
35+
}
36+
37+
```
38+
39+
40+
41+
42+
43+
444

545
滤镜的编写主要是靠基类。
646

@@ -16,14 +56,63 @@
1656

1757
RGB三个通道的颜色取反,而alpha通道不变。
1858

19-
### 灰色滤镜
59+
```gl
60+
//反向滤镜
61+
void reverse(inout vec4 color){
62+
color.r = 1.0 - color.r;
63+
color.g = 1.0 - color.g;
64+
color.b = 1.0 - color.b;
65+
}
66+
67+
```
68+
69+
### 黑白滤镜
70+
71+
```gals
72+
//黑白滤镜
73+
void blackAndWhite(inout vec4 color){
74+
float threshold = 0.5;
75+
float mean = (color.r + color.g + color.b) / 3.0;
76+
color.r = color.g = color.b = mean >= threshold ? 1.0 : 0.0;
77+
}
78+
```
79+
2080

21-
让RGB三个通道的颜色取均值
2281

2382
### 位移滤镜
2483

2584
纹理默认传入的读取范围是(0,0)到(1,1)内的颜色值。如果对读取的位置进行调整修改,那么就可以做出各种各样的效果,例如缩放动画就是让读取的范围改成(-1,-1)到(2,2)。
2685

86+
## 看完了疯了是不是,要做个滤镜效果,各种计算我实在弄不明白
87+
88+
最简单的方法就是通过LUT方法,通过设计师提供的LUT文件来实现预定的滤镜效果。基本思路如下:
89+
90+
- 准备LUT文件
91+
- 加载LUT文件到OpenGL纹理
92+
- 将纹理传递给片段着色器
93+
- 根据LUT,在片段着色器中对图像的颜色值进行映射,得到滤镜后的颜色进行输出
94+
95+
96+
97+
### 离屏渲染
98+
99+
之前已经将相机的预览数据输出到OpenGL的纹理上,渲染的时候OpenGL直接将纹理渲染到屏幕上。但是如果想要对纹理进行进一步的处理,就不能直接渲染到屏幕上,而是需要先渲染到屏幕外的缓冲区(FrameBuffer)处理完后再渲染到屏幕。渲染到缓冲区的操作就是离屏渲染。主要步骤如下:
100+
101+
- 准备离屏渲染所需要的FrameBuffer和纹理对象。
102+
- 切换渲染目标(屏幕->缓冲区)
103+
- 执行渲染
104+
- 重置渲染目标(缓冲区 -> 屏幕)
105+
106+
107+
108+
109+
110+
111+
112+
113+
114+
115+
27116

28117

29118

VideoDevelopment/OpenGL/5.OpenGL ES绘制三角形.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ Preferences -> Plugins -> 搜GLSL Support安装就可以了。
113113
```glsl
114114
// 声明着色器的版本
115115
#version 300 es
116-
// 顶点着色器的顶点位置,输入一个名为vPosition的4分量向量,layout (location = 0)表示这个变量的位置是顶点属性0
116+
// 顶点着色器的顶点位置,输入一个名为vPosition的4分量向量,layout (location = 0)表示这个变量的位置是顶点属性中的第0个属性
117117
layout (location = 0) in vec4 vPosition;
118-
// 顶点着色器的顶点颜色数据,输入一个名为aColor的4分量向量,layout (location = 1)表示这个变量的位置是顶点属性1
118+
// 顶点着色器的顶点颜色数据,输入一个名为aColor的4分量向量,layout (location = 1)表示这个变量的位置是顶点属性中的第1个属性
119119
layout (location = 1) in vec4 aColor;
120120
// 输出一个名为vColor的4分量向量,后面输入到片段着色器中。
121121
out vec4 vColor;
@@ -129,6 +129,8 @@ Preferences -> Plugins -> 搜GLSL Support安装就可以了。
129129
}
130130
```
131131

132+
大体意思:使用OpenGL ES3.0版本,将图形顶点数据采用4分向量的数据结构绑定到着色器的第0个属性上,属性的名字是vPosition,然后再有一个颜色的4分向量绑定到做色漆的第1个属性上,属性的名字是aColor,另外还会输出一个vColor,着色器执行的时候,会将vPosition的值传递给用来表示顶点最终位置的内建变量gl_Position,将顶点最终大小的gl_PointSize设置为10,并将aColor的值复制给要输出额vColor。
133+
132134
- 片段着色器(fragment_simple_shade.glsl)
133135

134136
```glsl
@@ -211,12 +213,12 @@ class MyGLRenderer implements GLSurfaceView.Renderer {
211213
/*****************1.声明绘制图形的坐标和颜色数据 end**************/
212214
public MyGLRenderer() {
213215
/****************2.为顶点位置及颜色申请本地内存 start************/
214-
//顶点位置相关
216+
//将顶点数据拷贝映射到native内存中,以便OpenGL能够访问
215217
//分配本地内存空间,每个浮点型占4字节空间;将坐标数据转换为FloatBuffer,用以传入给OpenGL ES程序
216-
vertexBuffer = ByteBuffer.allocateDirect(triangleCoords.length * BYTES_PER_FLOAT)
217-
.order(ByteOrder.nativeOrder())
218-
.asFloatBuffer();
219-
vertexBuffer.put(triangleCoords);
218+
vertexBuffer = ByteBuffer.allocateDirect(triangleCoords.length * BYTES_PER_FLOAT) // 直接分配native内存
219+
.order(ByteOrder.nativeOrder()) // 和本地平台保持一致的字节序
220+
.asFloatBuffer(); // 将底层字节映射到FloatBuffer实例,方便使用
221+
vertexBuffer.put(triangleCoords); // 将顶点数据拷贝到native内存中
220222
// 将数组数据put进buffer之后,指针并不是在首位,所以一定要position到0,至关重要!否则会有很多奇妙的错误!将缓冲区的指针移动到头部,保证数据是从最开始处读取
221223
vertexBuffer.position(0);
222224

@@ -258,9 +260,10 @@ class MyGLRenderer implements GLSurfaceView.Renderer {
258260
//把颜色缓冲区设置为我们预设的颜色,绘图设计到多种缓冲区类型:颜色、深度和模板。这里只是向颜色缓冲区中绘制图形
259261
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
260262

261-
//绑定vertex坐标数据,告诉OpenGL可以在缓冲区vertextBuffer中获取数据
263+
//0是上面着色器中写的vPosition的变量位置(location = 0)。意思就是绑定vertex坐标数据,然后将在vertextBuffer中的顶点数据传给vPosition变量。
264+
// 你肯定会想,如果我在着色器中不写呢?int vposition = glGetAttribLocation(program, "vPosition");就可以获得他的属性位置了
262265
GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);
263-
//启用顶点位置句柄
266+
//启用顶点变量,这个0也是vPosition在着色器变量中的位置,和上面一样,在着色器文件中的location=0声明的
264267
GLES30.glEnableVertexAttribArray(0);
265268

266269
//准备颜色数据

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ OpenGL中,2D纹理也有自己的坐标体系,取值范围在(0,0)到(1,1)
2828

2929
纹理上的每个顶点与定点坐标上的顶点一一对应。如下图,左边是顶点坐标,右边是纹理坐标,只要两个坐标的ABCD定义顺序一致,就可以正常地映射出对应的图形。顶点坐标内光栅化后的每个片段,都会在纹理坐标内取得对应的颜色值。
3030

31-
32-
3331
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/opengl_es_texture_position.jpg)
3432

3533
### 纹理尺寸
@@ -38,7 +36,7 @@ OpenGL中,2D纹理也有自己的坐标体系,取值范围在(0,0)到(1,1)
3836

3937
### 文件读取
4038

41-
OpenGL不能直接加载jpg或者png这类被编码的压缩格式,需要加载原始数据,也就是bitmpa。我们在内置图片到工程中,应该将图片放到drawable-nodpi中,避免读取时被压缩,通过BitmapFactory解码读取图片时,要设置为非缩放的方式,即options.isScaled=false。
39+
OpenGL不能直接加载jpg或者png这类被编码的压缩格式,需要加载原始数据,也就是bitmap。我们在内置图片到工程中,应该将图片放到drawable-nodpi中,避免读取时被压缩,通过BitmapFactory解码读取图片时,要设置为非缩放的方式,即options.isScaled=false。
4240

4341
### 纹理过滤
4442

@@ -212,7 +210,7 @@ public class TextureHelper {
212210
in vec2 vTexCoord;
213211
out vec4 vFragColor;
214212
void main() {
215-
// texture函数会从纹理贴图中读取
213+
// texture函数会将传进来的纹理和坐标进行差值采样,输出到颜色缓冲区。
216214
vFragColor = texture(uTextureUnit,vTexCoord);
217215
}
218216
```
@@ -262,6 +260,7 @@ public class TextureHelper {
262260
* 坐标占用的向量个数
263261
*/
264262
private static final int POSITION_COMPONENT_COUNT = 2;
263+
// 逆时针顺序排列
265264
private static final float[] POINT_DATA = {
266265
-0.5f, -0.5f,
267266
0.5f, -0.5f,
@@ -272,6 +271,7 @@ public class TextureHelper {
272271
* 颜色占用的向量个数
273272
*/
274273
private static final int TEXTURE_COMPONENT_COUNT = 2;
274+
// 纹理坐标(s, t),t坐标方向和顶点y坐标反着
275275
private static final float[] TEXTURE_DATA = {
276276
0.0f, 1.0f,
277277
1.0f, 1.0f,
@@ -313,10 +313,11 @@ public class TextureHelper {
313313
//在OpenGLES环境中使用程序
314314
GLES30.glUseProgram(mProgram);
315315

316-
316+
// 获取这三个属性在着色器中的属性位置
317317
uMatrixLocation = GLES30.glGetUniformLocation(mProgram, "u_Matrix");
318318
aPositionLocation = GLES30.glGetAttribLocation(mProgram, "vPosition");
319319
aTextureLocation = GLES30.glGetAttribLocation(mProgram, "aTextureCoord");
320+
// 将图片加载进来生成位图
320321
textureId = TextureHelper.loadTexture(MyApplication.getInstance(), R.drawable.img).getTextureId();
321322
}
322323

@@ -344,12 +345,12 @@ public class TextureHelper {
344345

345346
//将变换矩阵传入顶点渲染器
346347
GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, mProjectionMatrix, 0);
347-
//准备坐标数据
348+
//传入坐标数据
348349
GLES30.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GLES30.GL_FLOAT, false, 0, vertexBuffer);
349350
//启用顶点位置句柄
350351
GLES30.glEnableVertexAttribArray(aPositionLocation);
351352

352-
//准备颜色数据
353+
//传入颜色数据
353354
GLES30.glVertexAttribPointer(aTextureLocation, TEXTURE_COMPONENT_COUNT, GLES30.GL_FLOAT, false, 0, textureBuffer);
354355
//启用顶点颜色句柄
355356
GLES30.glEnableVertexAttribArray(aTextureLocation);

0 commit comments

Comments
 (0)