几何图元
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):位于顶点和片段着色器之间的一个 (可选的) 着色器,其输入是一个图元(如点或三角形)的一组顶点;可以在顶点发送到下一着色器阶段之前对它们随意变换。
一个简单的几何着色器例子:
1 2 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)物体:是指将每个三角形图元沿着法向量的方向移动一小段距离(效果就是,整个物体看起来像是沿着每个三角形的法线向量爆炸一样)。
几何着色器大致如下:
1 2 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();  }
   | 
 
法向量可视化
在写光照着色器的时候,有可能会得到一些奇怪的视觉输出,其原因有可能是法向量错误导致的;法向量错误可能是由于不正确加载顶点数据、错误地将其定义为顶点属性或在着色器中不正确地管理所导致的。
然而有一种很好用的方式可以检测法向量是否正确,那就是 法向量可视化;其实现思路如下:
- 首先不使用几何着色器正常绘制场景;
 
- 然后只显示通过几何着色器生成的法向量来绘制场景;
 
几何着色器大致如下:
1 2 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/。