金坛做网站哪家好,刚发布的手机,wordpress png,塘沽软件开发目录 一、说明二、关于几何着色器三、原始输入/输出规范3.1 实例 四、输入五、输出5.1 分层渲染 六、输出限制 一、说明
几何着色器对于渲染管线设计是一个新生事物#xff1b;目前对应于几何着色器的资料不多#xff0c;并且说法不一#xff0c;因此如何用几何着色器目前对应于几何着色器的资料不多并且说法不一因此如何用几何着色器依然需要参照当前管线的设计细节因而该手册也就是参考性的并非权威。
二、关于几何着色器
几何着色器是可选的不必使用。
几何着色器调用采用单个 Primitive 作为输入并且可以输出零个或多个 Primitive。对于可以从单个 GS 调用生成多少个基元存在实现定义的限制。编写 GS 以接受特定的输入基元类型并输出特定的基元类型。
虽然 GS 可用于放大几何图形从而实现粗略的曲面细分形式但这通常不是 GS 的良好用途。使用 GS 的主要原因是
分层渲染获取一个基元并将其渲染到多个图像而无需更改绑定的渲染目标等。变换反馈这通常用于在 GPU 上执行计算任务显然是预计算着色器。在 OpenGL 4.0 中GS 获得了两个新功能。一个是能够写入多个输出流。这专门用于转换反馈以便不同的反馈缓冲区集可以获取不同的转换反馈数据。
另一个功能是 GS 实例化它允许对同一输入原语进行多次调用。这使得分层渲染更易于实现并且可能执行得更快因为每个层的基元都可以由单独的 GS 实例计算。
注意虽然几何着色器以前有 GL_EXT_geometry_shader4 和 GL_ARB_geometry_shader4 等扩展但这些扩展以与核心功能截然不同的方式公开 API 和 GLSL 功能。本页仅介绍核心功能。 目录 一、说明二、关于几何着色器三、原始输入/输出规范3.1 实例 四、输入五、输出5.1 分层渲染 六、输出限制 三、原始输入/输出规范
每个几何着色器都设计为接受特定的 Primitive 类型作为输入并输出特定的 Primitive 类型。接受的输入基元类型在着色器中定义
layout(input_primitive) in;input_primitive类型必须与提供给 GS 的顶点流的基元类型匹配。如果启用了 Tessellation则基元类型由 Tessellation Evaluation Shader 的输出限定符指定。如果未启用 Tesslation则基元类型由使用此着色器程序渲染的绘图命令提供。input_primitive的有效值以及有效的 OpenGL 基元类型或曲面细分形式为
GS输入OpenGL 基元TES参数顶点计数点GL_POINTSpoint_mode1线GL_LINES、GL_LINE_STRIP GL_LINE_LOOP等值线2lines_adjacencyGL_LINES_ADJACENCYGL_LINE_STRIP_ADJACENCY不适用4三角形GL_TRIANGLES、GL_TRIANGLE_STRIP GL_TRIANGLE_FAN三角形、四边形3triangles_adjacencyGL_TRIANGLES_ADJACENCYGL_TRIANGLE_STRIP_ADJACENCY不适用6
顶点计数是 GS 接收的每个输入基元的顶点数。
输出基元类型定义如下
layout(output_primitive, max_vertices vert_count) out;output_primitive必须是以下项之一
pointline_striptriangle_strip
它们的工作方式与它们的对应 OpenGL 渲染模式完全相同。要输出单个三角形或直线只需在发出每组 3 或 2 个顶点后使用 EndPrimitive见下文。
输出必须有max_vertices声明。该数字必须是编译时常量它定义了 GS 的单次调用将写入的最大顶点数。它不能大于实现定义的MAX_GEOMETRY_OUTPUT_VERTICES限制。此限制的最小值为 256。请参阅下面的限制。
3.1 实例
GS 实例化 核心版本 4.6 核心自版本起 4.0 核心 ARB 扩展 ARB_gpu_shader5 GS 也可以实例化这与实例化渲染是分开的因为它已本地化到 GS。这会导致 GS 对同一输入基元执行多次。每次对特定输入原语的 GS 调用都会得到一个不同的gl_InvocationID值。这对于分层渲染和输出到多个流非常有用见下文。
若要使用实例化必须有一个输入布局限定符
layout(invocations num_instances) in;num_instances 的值不得大于 MAX_GEOMETRY_SHADER_INVOCATIONS至少为 32。内置值 gl_InvocationID 指定此着色器的特定实例;它将处于半开范围 [0 num_instances。
实例的输出基元按gl_InvocationID排序。因此如果用户渲染两个基元并将num_instances设置为 3则 GS 将按以下顺序有效调用prim0 inst0 prim0 inst1 prim0 inst2 prim1 inst0 …GS 的输出基元将根据该输入序列进行排序。因此如果 prim0 inst0 输出两个三角形则在渲染 prim0 inst1 中的任何三角形之前它们都将被渲染。
四、输入
几何着色器采用基元作为输入;每个基元都由一定数量的顶点组成这些顶点由着色器中的输入基元类型定义。
因此顶点着色器或 Tessellation Stage视情况而定的输出将作为变量数组馈送到 GS。这些变量可以组织为单个变量也可以组织为接口块的一部分。每个单独的变量都是一个与基元顶点计数长度相同的数组;对于接口块块本身将以此长度排列。输入数组中顶点的顺序对应于先前着色器阶段指定的顶点顺序。
几何着色器输入可能具有插值限定符。如果这样做则前一阶段的输出必须使用相同的限定符。
五 ·E 几何着色器提供以下内置输入变量
in gl_PerVertex
{vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];
} gl_in[];这些变量仅具有通过它们的先前着色器阶段赋予它们的含义。
有些 GS 输入值基于基元而不是顶点。这些不会聚合到数组中。这些是
in int gl_PrimitiveIDIn;
in int gl_InvocationID; // Requires GLSL 4.0 or ARB_gpu_shader5
gl_PrimitiveIDIn当前输入基元的 ID基于自当前绘图命令启动以来 GS 处理的基元数。 gl_InvocationID 实例化几何着色器时定义的当前实例。
五、输出
几何着色器可以根据需要输出任意数量的顶点最多为 max_vertices 布局规范指定的最大值。为此几何着色器中的输出值不是数组。相反使用基于函数的接口。
GS 代码写入顶点的所有输出值然后调用 EmitVertex。这告诉系统将这些输出值写入输出顶点的写入位置。调用此函数后所有输出变量都包含未定义的值。因此在发出下一个顶点如果有下一个顶点之前您需要再次写入它们。
注意您必须在每次 EmitVertex 调用之前写入每个输出变量对于每个 EmitStreamVertex 调用的流的所有输出。 GS 定义了这些顶点输出所代表的基元类型。GS 还可以通过调用 EndPrimitive 函数来结束基元并启动新基元。这不会发出顶点。
为了从 GS 写入两个独立的三角形您必须使用前三个顶点的 EmitVertex 编写三个单独的顶点然后调用 EndPrimitive 以结束条带并启动一个新条带。然后你用 EmitVertex 再写三个顶点。
对于 GLSL输出变量定义为正常变量。根据需要它们可以分组为接口块或单个值。可以使用插值限定符定义输出变量。Fragment Shader 等效接口变量应使用相同的限定符定义相同的变量。
五 ·E 几何着色器具有以下内置输出。
out gl_PerVertex
{vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];
};gl_PerVertex定义了输出的接口块。该块在没有实例名称的情况下定义因此不需要在名称前加上前缀。
GS 是最后的顶点处理阶段。因此除非关闭栅格化否则必须写入其中一些值。这些输出始终与流 0 相关联。因此如果要向其他流发出顶点则不必写入它们。
gl_Position 当前顶点的剪辑空间输出位置。如果要向流 0 发出顶点则必须写入此值除非栅格化处于关闭状态。 gl_PointSize 被栅格化的点的像素宽度/高度。只有在输出点基元时才需要写入它。 gl_ClipDistance 允许着色器设置从顶点到每个用户定义的裁剪平面的距离。正距离表示顶点位于裁剪平面的内部/后面负距离表示顶点位于裁剪平面的外部/前面。为了使用此变量用户必须手动重新声明它以及接口块并具有显式大小。 某些预定义的输出具有特殊的含义和语义。
out int gl_PrimitiveID;原始 ID 将传递给片段着色器。特定直线/三角形的原始 ID 将从该直线/三角形的挑衅顶点中获取因此请确保为正确的挑衅顶点编写正确的值。
这个值的含义是你想要的。但是如果要匹配标准的 OpenGL 含义即如果不使用 GSFragment Shader 会得到什么则必须在发出之前对每个顶点执行此操作
gl_PrimitiveID gl_PrimitiveIDIn;这自然假设 GS 输出的基元数等于 GS 接收的基元数。
5.1 分层渲染
分层渲染是让 GS 将特定基元发送到分层帧缓冲区的不同层的过程。这对于执行基于立方体的阴影贴图非常有用甚至可以用于渲染立方体环境贴图而无需多次渲染整个场景。
五 ·E GS 中的分层渲染通过两个特殊的输出变量工作
out int gl_Layer;
out int gl_ViewportIndex; // Requires GL 4.1 or ARB_viewport_array.gl_Layer输出定义基元转到分层图像中的哪个层。基元中的每个顶点都必须获得相同的层索引。请注意当渲染到立方体贴图数组时gl_Layer值表示图层面图层中的面而不是立方体贴图的层。
gl_ViewportIndex需要 GL 4.1 或 ARB_viewport_array它指定要与此基元一起使用的视口索引。
注意ARB_viewport_array虽然在技术上是一项 4.1 功能但在 NVIDIA 和 AMD 的 3.3 硬件上广泛可用。 使用 GS 实例化可以提高分层渲染的效率因为不同的 GS 调用可以并行处理实例。但是虽然 ARB_viewport_array 通常在 3.3 硬件中实现但没有 3.3 硬件提供ARB_gpu_shader5支持。
警告gl_Layer 和 gl_ViewportIndex 是 GS 输出变量。因此每次调用 EmitVertex 时它们的值都将变为未定义。因此每次循环输出时都必须设置这些变量。 如果几何着色器从不写入 gl_ViewportIndex则所有内容的行为就像写入 0 一样。
哪个顶点 gl_Layer 和 gl_ViewportIndex 是每个顶点的参数但它们指定了适用于整个基元的属性。因此出现了一个问题特定基元中的哪个顶点定义了该基元的图层和视口索引
答案是它依赖于实现。但是OpenGL 确实有两个查询来确定当前实现使用哪一个GL_LAYER_PROVOKING_VERTEX 和 GL_VIEWPORT_INDEX_PROVOKING_VERTEX。
从 glGetIntegerv 返回的值将是以下枚举器之一
GL_PROVOKING_VERTEX使用的顶点将跟踪当前激发的顶点约定。GL_LAST_VERTEX_CONVENTION使用的顶点将由最后一个顶点激发顶点约定定义的顶点。GL_FIRST_VERTEX_CONVENTION使用的顶点将由第一个顶点激发顶点约定定义的顶点。GL_UNDEFINED_VERTEX实现不是说。 为了获得最大的可移植性您必须为每个基元提供相同的图层和视口索引。因此如果您想输出一个三角形条带其中不同的三角形具有不同的索引那就太糟糕了。您必须将其拆分为不同的基元。
输出流 输出流 核心版本 4.6 核心自版本起 4.0 核心 ARB 扩展 ARB_transform_feedback3 使用变换反馈计算值时能够以不同的速率将不同的顶点集发送到不同的缓冲区通常很有用。例如GS 可以将顶点数据发送到一个流同时在另一个流中构建每个实例的数据。顶点数据和每个实例的数据将具有不同的长度以不同的速度写入。
多流输出要求输出基元类型为点。您仍然可以接受您喜欢的任何输入。
为了提供这一点可以为输出变量提供带有布局限定符的流索引 layout(stream stream_index) out vec4 some_output;stream_index范围从 0 到 GL_MAX_VERTEX_STREAMS - 1。
可以使用以下命令设置流的默认值
layout(stream 2) out;所有以下变量都将使用流 2除非它们指定了流。以后可以更改默认值。初始默认值为 0。
若要将顶点写入特定流请使用函数 EmitStreamVertex。此函数采用流索引;仅写入这些输出变量。同样EndStreamPrimitive 结束特定流的基元。但是由于多流输出需要使用点基元因此后一个函数不是很有用。
实际上只有发送到流 0 的基元才会传递给 Vertex Post-Processing 并呈现;其余的流只有在使用转换反馈时才有意义。调用 EmitVertex 或 EndPrimitive 等同于使用流 0 调用它们的流对应项。
六、输出限制
几何着色器的输出存在两个相互竞争的限制
GS 的单次调用可以输出的最大顶点数。GS 的单次调用可以输出的最大输出组件总数。 第一个限制由 GL_MAX_GEOMETRY_OUTPUT_VERTICES 定义是可以提供给max_vertices输出布局限定符的最大数量。单个几何着色器调用都不能超过此数字。
另一个限制由 GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 定义通俗地说是单个 GS 调用可以写入的内容总量。它是输出值的总数在 GLSL 术语中分量是向量的分量。所以浮点数是一个组成部分;vec3 是单个 GS 调用可以写入的 3 个组件。这与 GL_MAX_GEOMETRY_OUTPUT_COMPONENTS输出变量中允许的最大组件数不同。总输出分量是可以写入的分量总数 顶点。
例如如果总输出组件计数为 1024GL 4.3 中的最小最大值并且输出流写入 12 个组件则可写入的顶点总数为 f l o o r 1024 12 85 {\displaystyle floor{\tfrac {1024}{12}}85} floor12102485 这是对可以写入的顶点数的绝对硬性限制。即使GL_MAX_GEOMETRY_OUTPUT_VERTICES大于 85由于此顶点着色器为每个顶点写入 12 个分量因此此几何着色器可以写入的真正最大值为 85 个顶点。如果几何着色器每个顶点只写入 8 个分量那么它可以写入 128 个分量当然受输出顶点限制的约束。
请注意即使是像 gl_Layer 这样的内置输出也计入GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS。例如总输出组件计数为 1024 的几何着色器输出 vec4 gl_Position 和 int gl_Layer 最多支持 f l o o r 1024 4 1 204 {\displaystyle floor{\tfrac {1024}{41}}204} floor411024204
顶点。