OpenGL 编程指南 (9)

 

1、几何着色器(geometry shader)负责处理一个完成图元的顶点数据,重点在于一个完整的图元,经过它的处理后能够改变图元的图元类型、数目。

  void EmitVertex();//完成了一个顶点的处理

  void EndPrimitive();//标志完成了一个图元的顶点处理,生成一个图元

 

2、几何着色器首先需要声明的是接受的图元输入类型、输出的图元类型与最大顶点数目如下:

  layout (lines) in;//指定的图元类型需要与绘制几何图形的命令匹配(注意GL_PATCHES)

  layout (line_strip, max_vertices = 6) out;//输出的图元类型必须是line_strip、triangle_strip、points中的一种

 

3、上面例子给定的输入图元为lines,那么图元的顶点数据应该为2个顶点数据,可以在gl_in中获取,数据长度也可用gl_in.length()获得。从此也能够类比出几何着色器的其它输入都应该是数组。

 

4、几个特殊的变量:gl_PrimitiveIDIn 这个输入变量表示的是当前处理的第几个图元,需要与 gl_PrimitiveID 区分,这个是几何着色器的输出变量;gl_InvocationID 是用于实现实例化的变量。因为图元的数量经过几何着色器后可能会发生变化,gl_PrimitiveID作为输出需要gl_PrimitiveIDIn作为参数进行调整。

 

5、lines_adjacency、triangle_adjacency都是带有邻接顶点的图元类型。lines_adjacency带有四个顶点,中间两个才是线段的顶点;triangle_adjacency带有6个顶点,0、1、3是三角形的顶点。

 

6、glsl内调用了EmitVertex后,所有顶点信息将会恢复到未定义状态,再次调用EnitVertex之前需要写入顶点信息,除非使用了flat关键字。provoking vertex的顶点值会用于后续阶段,只要不被使用即使没有定义也没关系。一个几何着色器输出的顶点数量是有限的,通过内建变量gl_MaxGeometryOutputVertices(这么长的名字???)或GL_MAX_GEOMETRY_OUTPUT_VERTICES来获取。

  void glProvokingVertex(GLenum provokeMode);//GL_LAST_VERTEX_CONVENTION、GL_FIRST_VERTEX_CONVENTION表示使用图元的最后一个顶点或者是第一个进行扁平插值

  下面是一个完整的例子

7、多重输出流

  1)几何着色器可以声明多组输出的顶点数据流,使用布局限定符stream,可全局修饰变量、修饰单一变量或接口块,stream的标号从0(默认值)开始,最大值通过GL_MAX_VERTEX_STREAMS获取至少是4。启用多输出流的几何着色器需要使用EmitStreamVertex(int stream)与EndStreamPrimitive(int stream)指定数据输出到哪一个流。

 

 

 

 2)开启光栅化,0输出流中的数据将被用于构建图元进行光栅化后传递到fragment shader,其它的输出流的数据将被丢弃

 3)几何着色器中使用了多输出流,那么图元类型必须是points

 

8、需要查询几何着色器输出了多少图元以及写入transform feedback的内容大小,需要查询GL_PRIMITIVES_GENERATED(生成的顶点数量)、GL_TRANSFORM_FEEDBACK_PRIMTIVES_WRITTING(写入到反馈缓冲顶点的数量)。对于多输出流的查询需要指定流的编号,如下:

  void glBeginQueryIndexed(GLenum target, GLuint index, GLuint id)

  void glEndQueryIndexed(GLenum target, GLuint index)

 

9、利用transform feedback缓冲中顶点数据进行绘制最直观的方法是将数据从GPU读回CPU然后像平时一样进行绘制,可想而知数据流通的消耗。因此OpenGL提供了下面的方法使用缓冲内容直接进行绘制。

  void glDrawTransformFeedback(GLenum mode, GLuint id)//mode为图元类型,id为transform feedback对象id,相对于glDrawArrays参数的first与count分别被认定为0与反馈缓冲捕获图元数量(这里对于count的说法 gl API网站上的说明用的是vertices,写代码实地考察的结果是图元数目)

  void glDrawTransformFeedbackStream(GLenum mode, GLuint id, GLuint stream)//stream输出流的id

  void glDrawTransformFeedbackInstanced(GLenum mode, GLuint id, GLsizei instancecount)

  void glDrawTransformFeedbackStreamInstanced(GLenum mode, GLuint id, GLuint stream, GLsizei instancecount)

 

10、https://www.khronos.org/opengl/wiki/Geometry_Shader

 

posted @ 2020-03-08 14:27  no-being  阅读(613)  评论(0编辑  收藏  举报