GLSL 高级教程 – Geometry Shader Examples

本文通过三个示例介绍了简单几何着色器的应用:传递式着色器、复制几何体及将三角形一分为二的技术。这些示例展示了如何在不修改顶点属性的情况下进行几何处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In this page a set of examples of simple geometry shaders will be provided, to illustrate some of the features mentioned in the  previous page.

Example 1 – a pass-through shader

This example assume the same vertex shader as presented previous.

This shader does not change the attributes that came from the vertex shader, nor does it add, or remove, any information. This is sort of a “hello world” for geometry shader.

#version 150
 
layout(triangles) in;
layout (triangle_strip, max_vertices=3) out;
 
in VertexData {
    vec2 texCoord;
    vec3 normal;
} VertexIn[3];
 
out VertexData {
    vec2 texCoord;
    vec3 normal;
} VertexOut;
 
 void main()
{
  for(int i = 0; i < gl_VerticesIn; i++)
  {
     // copy attributes
    gl_Position = gl_in[i].gl_Position;
    VertexOut.normal = VertexIn[i].normal;
    VertexOut.texCoord = VertexIn[i].texCoord;
 
    // done with the vertex
    EmitVertex();
  }
}

The layout definitions state that the inputs are triangles, and the output are triangle strips, each with 3 vertices, i.e. a single triangle.

The geometry shader receives as inputs, for each vertex, user defined attributes for the texture coordinates and normals, in a named block that matches the output from the vertex shader. It also receives gl_Position.

The outputs are similar to the vertex shader. A named block for the vertex data, and gl_Position.

Example 2 – duplicate geometry

This shader assumes a vertex shader that acts as a pass-through, i.e. without modifying the vertex attributes, such as the one below.

#version 410
 
in vec3 position;
in vec3 normal;
in vec2 texCoord;
 
out VertexData {
    vec2 texCoord;
    vec3 normal;
} VertexOut;
 
void main()
{
    VertexOut.texCoord = texCoord;
    VertexOut.normal = normal;
    gl_Position = vec4(position, 1.0);
}

The geometry shader receives each primitive and duplicates it, displacing the second copy by 20 units in the X axis.

#version 420
 
layout(triangles) in;
layout (triangle_strip, max_vertices=6) out;
 
layout (std140) uniform Matrices {
    mat4 projModelViewMatrix;
    mat3 normalMatrix;
};
 
in VertexData {
    vec2 texCoord;
    vec3 normal;
} VertexIn[];
 
out VertexData {
    vec2 texCoord;
    vec3 normal;
} VertexOut;
 
 void main()
{
  for(int i = 0; i < gl_VerticesIn; i++)
  {
     // copy attributes
    gl_Position = projModelViewMatrix * gl_in[i].gl_Position;
    VertexOut.normal = normalize(normalMatrix * VertexIn[i].normal);
    VertexOut.texCoord = VertexIn[i].texCoord;
 
    // done with the vertex
    EmitVertex();
  }
  EndPrimitive();
 
  for(int i = 0; i < gl_VerticesIn; i++)
  {
     // copy attributes and displace copy
    gl_Position = projModelViewMatrix * (gl_in[i].gl_Position + vec4(20.0, 0.0, 0.0, 0.0));
    VertexOut.normal = normalize(normalMatrix * VertexIn[i].normal);
    VertexOut.texCoord = VertexIn[i].texCoord;
 
    // done with the vertex
    EmitVertex();
  }
  EndPrimitive();
}

Notice that we added the EndPrimitive instruction. This is because, in this example, we are outputting two primitives, two triangle strips. Hence, we have to tell the shader where the primitives end. Actually the last EndPrimitive instruction is optional, since when the shader terminates the primitive is also concluded, but it is nicer to have it there.

Example 3 – divide that triangle (in two)

This next example assumes the same vertex shader as the previous example. For each triangle it receives, it creates a strip with two triangles, which occupy the same space, by adding a vertex in the midpoint of an edge of the original triangle.

#version 420
 
layout(triangles) in;
layout (triangle_strip, max_vertices=4) out;
 
layout (std140) uniform Matrices {
    mat4 projModelViewMatrix;
    mat3 normalMatrix;
};
 
in VertexData {
    vec2 texCoord;
    vec3 normal;
} VertexIn[];
 
out VertexData {
    vec2 texCoord;
    vec3 normal;
} VertexOut;
 
 void main()
{
     // copy attributes for the first vertex
    gl_Position = projModelViewMatrix * gl_in[0].gl_Position;
    VertexOut.normal = normalize(normalMatrix * VertexIn[0].normal);
    VertexOut.texCoord = VertexIn[0].texCoord;
    EmitVertex();
 
     // copy attributes for the second vertex
    gl_Position = projModelViewMatrix * gl_in[1].gl_Position;
    VertexOut.normal = normalize(normalMatrix * VertexIn[1].normal);
    VertexOut.texCoord = VertexIn[1].texCoord;
    EmitVertex();
 
    // this is the new vertex
    gl_Position = projModelViewMatrix * (gl_in[0].gl_Position + gl_in[2].gl_Position);
    VertexOut.normal = normalize(normalMatrix * (VertexIn[0].normal + VertexIn[2].normal));
    VertexOut.texCoord = VertexIn[0].texCoord +  VertexIn[2].texCoord;
    EmitVertex();
 
     // copy attributes for the last vertex
    gl_Position = projModelViewMatrix * gl_in[2].gl_Position;
    VertexOut.normal = normalize(normalMatrix * VertexIn[2].normal);
    VertexOut.texCoord = VertexIn[2].texCoord;
    EmitVertex();
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值