计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 10.增强表面细节(一)过程式凹凸贴图

发布于:2025-05-16 ⋅ 阅读:(21) ⋅ 点赞:(0)

1. 增强表面细节

我们想要展现不规则表面的物体,例如橘子凹凸的表面、葡萄干褶皱的表面或月球的陨石坑表面。
有以下办法:

  1. 该物体模型本身就具有凹凸的表面,这种方式最直接,但这样的模型会非常复杂,而且可能无法制作,同时由于顶点数目太多,可能无法在GPU上渲染。
  2. 用一个纹理贴图来表示表面的凹凸,这种方式最简单,但由于纹理贴图是静态的,所以无法表现动态的物体。同时由于光照变化的,也会给人不真实的感觉。
  3. 采用过程式凹凸贴图、法线贴图等方式,这种方式比较合适,顶点数并没有额外增加,同时又能适应光照变化。即如果 我们想让一个物体看起来好像有凹凸(或皱纹、坑洼等),通过计算表面确实凹凸不平时其上的法向量。当场景被照亮时,光照会让人产生我们所期望的“幻觉”。

1.1. 过程式凹凸贴图

过程式凹凸贴图是一种在3D图形渲染中用于增强表面细节的技术,它通过数学函数或算法来动态计算表面法线的扰动,从而在不增加几何复杂度的情况下创造出表面凹凸的视觉效果。

1.1.1. 主要特点:

  1. 动态计算

    • 不需要预先制作纹理图
    • 可以实时生成表面细节
    • 能够创造出动态变化的效果
  2. 资源效率

    • 不增加模型的多边形数量
    • 内存占用小
    • GPU负载相对较低
  3. 灵活性

    • 可以通过修改算法参数来调整效果
    • 适合生成规则的纹理模式
    • 可以与其他贴图技术结合使用

1.1.2. 工作原理:

  1. 在着色器中通过数学函数计算法线偏移
  2. 修改原始法线方向
  3. 使用修改后的法线进行光照计算
  4. 产生凹凸的视觉效果

1.1.3. 常见应用:

  • 水面波纹效果
  • 规则的网格纹理
  • 程序化生成的地形细节
  • 动态的表面扰动

与传统的凹凸贴图相比,过程式凹凸贴图更适合表现动态变化的表面效果,并且不受贴图分辨率的限制。

1.1.4. 顶点着色器

 originalVertPos = vertPos; // 保存原始顶点位置

1.1.5. 片段着色器

核心代码是计算新的法线向量,一种方式是取该顶点的原始模型顶点坐标(即新的变量x,y,z)与经过插值后的法线向量进行运算,另一种方式是将x,y,z设置成其它值 。

void main(void)
{   
    // 标准化光照计算所需的向量
    vec3 L = normalize(varyingLightDir);    // 光源方向向量
    //vec3 N = normalize(varyingNormal);      // 表面法线向量

    float x=originalVertPos.x;
    float y=originalVertPos.y;  
    float z=originalVertPos.z;

    // float x=varyingNormal.x;
    // float y=varyingNormal.y;  
    // float z=varyingNormal.z;

    float a=0.25f;
    float b=100;
    vec3 N=normalize(varyingNormal+vec3(a*sin(b*x),a*sin(b*y),a*sin(b*z)));
    //...
}

下图是采用如下代码:

    float x=originalVertPos.x;
    float y=originalVertPos.y;  
    float z=originalVertPos.z;

[外链图片转存中…(img-y4Vo0ykS-1747196284759)]

下图是采用如下代码:

    float x=varyingNormal.x;
    float y=varyingNormal.y;  
    float z=varyingNormal.z;

[外链图片转存中…(img-OTprK0HM-1747196284759)]

1.2. 参考

  1. 学习笔记完整代码下载
  2. OpenGL shader开发实战学习笔记:第十章 法线贴图_法线贴图是什么意思-CSDN博客

网站公告

今日签到

点亮在社区的每一天
去签到