几何图元
glDrawArrays(GLenum mode, GLint first, GLsizei count); 和 glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); 是用于会渲染绘制图形的。
其参数 mode 表示几何图元的描述类型,常见的类型如下:
- GL_POINTS:单个顶点集;为- n个顶点的每一个都绘制一个点;示意图如下:
 -     
 
- GL_LINES:多组双顶点线段;两个顶点解释为一条直线,直线之间并不连接(如果奇数个顶点,最后一个将忽略);示意图如下:
 -    
 
- GL_LINE_LOOP:闭合折线;从- v1到- vN一系列的直线且构成环;示意图如下
 -    
 
- GL_LINE_STRIP:不闭合折线; 从- v1到- vN一系列的直线;示意图如下:
 -    
 
- GL_TRAINGLES:多组独立填充三角形;一系列的三角形(- 3的倍数个顶点,多余的将忽略);示意图如下:
 -    
 
- GL_TRAINGLE_STRIP:线型连续填充三角形串;- (v1,v2,v3),- (v2,v3,v4),依次类推(所有的三角形是按相同方向绘制);示意图如下:
 -    
 
- GL_TRAINGLE_FAN:扇形连续填充三角形串;- (v1,v2,v3),- (v1,v3,v4),以此类推(一直是以- v1开始);示意图如下:
 -    
 
几何着色器
几何着色器(Geometry Shader):位于顶点和片段着色器之间的一个 (可选的) 着色器,其输入是一个图元(如点或三角形)的一组顶点;可以在顶点发送到下一着色器阶段之前对它们随意变换。
一个简单的几何着色器例子:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 
 | #version 330 core       /* 指定 GLSL 版本3.3,匹配 OpenGL 版本 */
 layout (points) in;
 
 layout (line_strip, max_vertices = 2) out;
 
 
 
 
 
 
 
 
 
 
 void main()
 {
 
 gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0);
 
 
 EmitVertex();
 
 
 gl_Position = gl_in[0].gl_Position + vec4( 0.1, 0.0, 0.0, 0.0);
 
 EmitVertex();
 
 
 EndPrimitive();
 }
 
 | 
几何着色器“输入”的图元类型:
- points:绘制- GL_POINTS图元时(最小顶点数:1)。
- lines:绘制- GL_LINES或- GL_LINE_STRIP时(最小顶点数:2)。
- lines_adjacency:绘制- GL_LINES_ADJACENCY或- GL_LINE_STRIP_ADJACENCY时(最小顶点数:4)。
- triangles:绘制- GL_TRIANGLES、- GL_TRIANGLE_STRIP或- GL_TRIANGLE_FAN时(最小顶点数:3)。
- triangles_adjacency:绘制- GL_TRIANGLES_ADJACENCY或- GL_TRIANGLE_STRIP_ADJACENCY时(最小顶点数:6)。
几何着色器“输出”的图元类型:
- **points**。
- **line_strip**。
- **triangle_strip**。
爆破物体
爆破(Explode)物体:是指将每个三角形图元沿着法向量的方向移动一小段距离(效果就是,整个物体看起来像是沿着每个三角形的法线向量爆炸一样)。
几何着色器大致如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 
 | #version 330 core       /* 指定 GLSL 版本3.3,匹配 OpenGL 版本 */
 layout (triangles) in;
 
 layout (triangle_strip, max_vertices = 3) out;
 
 
 
 
 in VS_OUT {
 vec2 texCoords;
 } gs_in[];
 
 out vec2 TexCoords;
 
 uniform float timeValue;
 
 
 
 
 
 
 vec3 GetNormal()
 {
 
 vec3 a = vec3(gl_in[0].gl_Position) - vec3(gl_in[1].gl_Position);
 
 vec3 b = vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position);
 
 return normalize(cross(a, b));
 }
 
 
 
 
 
 
 
 
 vec4 explode(vec4 position, vec3 normal)
 {
 float magnitude = 0.5;
 
 vec3 direction = normal * ((sin(timeValue) + 1.0) / 2.0) * magnitude;
 
 return position + vec4(direction, 0.0);
 }
 
 void main()
 {
 vec3 normal = GetNormal();
 
 gl_Position = explode(gl_in[0].gl_Position, normal);
 TexCoords = gs_in[0].texCoords;
 EmitVertex();
 gl_Position = explode(gl_in[1].gl_Position, normal);
 TexCoords = gs_in[1].texCoords;
 EmitVertex();
 gl_Position = explode(gl_in[2].gl_Position, normal);
 TexCoords = gs_in[2].texCoords;
 EmitVertex();
 EndPrimitive();
 }
 
 | 
法向量可视化
在写光照着色器的时候,有可能会得到一些奇怪的视觉输出,其原因有可能是法向量错误导致的;法向量错误可能是由于不正确加载顶点数据、错误地将其定义为顶点属性或在着色器中不正确地管理所导致的。
然而有一种很好用的方式可以检测法向量是否正确,那就是 法向量可视化;其实现思路如下:
- 首先不使用几何着色器正常绘制场景;
- 然后只显示通过几何着色器生成的法向量来绘制场景;
几何着色器大致如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 
 | #version 330 core       /* 指定GLSL版本3.3,匹配 OpenGL 版本 */
 layout (triangles) in;
 
 layout (line_strip, max_vertices = 6) out;
 
 
 
 
 in VS_OUT {
 vec3 normal;
 } gs_in[];
 
 const float magnitude  = 0.1;
 
 
 
 
 
 
 void GenerateNormal(int index)
 {
 gl_Position = gl_in[index].gl_Position;
 EmitVertex();
 
 gl_Position = gl_in[index].gl_Position + vec4(gs_in[index].normal, 0.0) * magnitude ;
 EmitVertex();
 EndPrimitive();
 }
 
 void main()
 {
 
 for (int index = 0; index < 3; index++)
 {
 GenerateNormal(index);
 }
 }
 
 | 
参考
教程来源:https://learnopengl.com/。