1. 爆炸效果
这是几何着色器中的一个常见应用,我们使用几何着色器来模拟爆炸效果。
我们希望将每个三角形沿其表面法向量向外移动,则实际上是将组成环面的三角形向外“爆炸”。
我们只需取三个顶点的法向量,然后将其相加并求平均,即可得到环面的法向量。这样就能形成爆炸效果。
1.1. 代码
只需修改几何着色器即可,主要修改为红框部份:
完整代码如下
#version 430
// 定义输入图元类型为三角形
layout (triangles) in;
// 从顶点着色器接收的输入变量(必须声明为数组)
in vec3 varyingNormal[]; // 法线向量数组
in vec3 varyingLightDir[]; // 光照方向数组
in vec3 varyingVertPos[]; // 顶点位置数组
// 传递给片段着色器的输出变量
out vec3 gNormal; // 法线向量
out vec3 gLightDir; // 光照方向
out vec3 gVertPos; // 顶点位置
// uniform变量声明
uniform mat4 proj_matrix; // 投影矩阵
uniform mat4 norm_matrix; // 法线变换矩阵
// 定义输出图元类型为三角形带,每个图元最多输出3个顶点
layout (triangle_strip, max_vertices = 3) out;
void main(void)
{
vec3 triangleNormal=(varyingNormal[0] + varyingNormal[1] + varyingNormal[2]) / 3.0;
// 处理三角形的每个顶点
for (int i = 0; i < 3; i++)
{
// 计算膨胀效果
//vec3 normal = normalize(varyingNormal[i]); // 归一化法线向量
vec3 normal = normalize(triangleNormal); // 归一化法线向量
// 将顶点沿法线方向移动(膨胀效果)
//gl_Position = proj_matrix * gl_in[i].gl_Position + normalize(vec4(normal, 1.0));
gl_Position =proj_matrix*( gl_in[i].gl_Position + normalize(vec4(normal, 1.0)) * 0.5);
// 将变量传递给片段着色器
gNormal = varyingNormal[i]; // 传递法线
gLightDir = varyingLightDir[i]; // 传递光照方向
gVertPos = varyingVertPos[i]; // 传递顶点位置
// 发射顶点
EmitVertex();
}
// 结束当前图元的构建
EndPrimitive();
}
2. 修改图元类型
上图是将三角形图元修改为线段图元,我们只需要修改几何着色器即可,
核心思路是形成新的两个点
完整代码如下
#version 430
// 点光源结构体定义
struct PositionalLight
{
vec4 ambient; // 环境光分量
vec4 diffuse; // 漫反射分量
vec4 specular; // 镜面反射分量
vec3 position; // 光源位置
};
// 定义输入图元类型为三角形
layout (triangles) in;
// 从顶点着色器接收的输入变量(必须声明为数组)
in vec3 varyingNormal[]; // 法线向量数组
in vec3 varyingLightDir[]; // 光照方向数组
in vec3 varyingVertPos[]; // 顶点位置数组
// 传递给片段着色器的输出变量
out vec3 gNormal; // 法线向量
out vec3 gLightDir; // 光照方向
out vec3 gVertPos; // 顶点位置
// uniform变量声明
uniform mat4 proj_matrix; // 投影矩阵
uniform mat4 norm_matrix; // 法线变换矩阵
uniform PositionalLight light; // 点光源属性
layout (line_strip, max_vertices = 2) out;
void main(void)
{
float sLen=0.5;
vec3 op0 = gl_in[0].gl_Position.xyz; // 原始三角形顶点
vec3 op1 = gl_in[1].gl_Position.xyz;
vec3 op2 = gl_in[2].gl_Position.xyz;
vec3 ep0 = gl_in[0].gl_Position.xyz + varyingNormal[0]*sLen; // 偏移三角形顶点
vec3 ep1 = gl_in[1].gl_Position.xyz + varyingNormal[1]*sLen;
vec3 ep2 = gl_in[2].gl_Position.xyz + varyingNormal[2]*sLen;
// 计算组成小线段的新点
vec3 newPoint1 = (op0 + op1 + op2)/3.0; // 原始点(起点)
vec3 newPoint2 = (ep0 + ep1 + ep2)/3.0; // 终点
gl_Position = proj_matrix * vec4(newPoint1, 1.0);
gVertPos = newPoint1;
gLightDir = light.position - newPoint1;
gNormal = varyingNormal[0];
EmitVertex();
gl_Position = proj_matrix * vec4(newPoint2, 1.0);
gVertPos = newPoint2;
gLightDir = light.position - newPoint2;
gNormal = varyingNormal[1];
EmitVertex();
// 结束当前图元的构建
EndPrimitive();
}