计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 13.几何着色器(二)爆炸效果&修改图元类型

1. 爆炸效果

这是几何着色器中的一个常见应用,我们使用几何着色器来模拟爆炸效果。

我们希望将每个三角形沿其表面法向量向外移动,则实际上是将组成环面的三角形向外"爆炸"。

我们只需取三个顶点的法向量,然后将其相加并求平均,即可得到环面的法向量。这样就能形成爆炸效果。

1.1. 代码

只需修改几何着色器即可,主要修改为红框部份:

完整代码如下

c++ 复制代码
#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. 修改图元类型

上图是将三角形图元修改为线段图元,我们只需要修改几何着色器即可,

核心思路是形成新的两个点

完整代码如下

C++ 复制代码
#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();
}
相关推荐
嵌入式×边缘AI:打怪升级日志11 分钟前
Makefile 完全学习笔记:从入门到通用模板解析
笔记·学习
仲芒11 分钟前
[24年单独笔记] MySQL 引擎架构
笔记·mysql·架构
Mr YiRan14 分钟前
JNI技术之手写JNIEnv与静态缓存与native异常
java·c++
ACGkaka_18 分钟前
ES 学习(九)从文本到词元:分词器如何“拆解“你的数据
大数据·学习·elasticsearch
飞翔的SA20 分钟前
全程 Python:无需离开 Python 即可实现光速级 CUDA 加速,无需c++支持
开发语言·c++·python·nvidia·cuda
南無忘码至尊22 分钟前
Unity学习90天-第1天-认识Unity并书写我们的第一个脚本
学习·unity·游戏引擎
SccTsAxR25 分钟前
算法进阶:贪心策略证明全攻略与二进制倍增思想深度解析
c++·经验分享·笔记·算法
2301_7926748631 分钟前
java学习day27(算法)
java·学习·算法
CoderMeijun33 分钟前
CMake 入门笔记
c++·笔记·编译·cmake·构建工具
zhangrelay33 分钟前
蓝桥云课一分钟-星界战纪-Stellar Combat-make
笔记·学习