OpenGL超级宝典第八章学习笔记:基元处理之曲面细分

这篇具有很好参考价值的文章主要介绍了OpenGL超级宝典第八章学习笔记:基元处理之曲面细分。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言
本篇在讲什么

OpenGL蓝宝书第八章学习笔记之曲面细分
本篇适合什么

适合初学OpenGL的小白
本篇需要什么

C++语法有简单认知
OpenGL有简单认知
最好是有OpenGL超级宝典蓝宝书
依赖Visual Studio编辑器

本篇的特色

具有全流程的图文教学
重实践,轻理论,快速上手
提供全流程的源码内容

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分
★提高阅读体验★

👉 ♠ 一级标题 👈

👉 ♥ 二级标题 👈

👉 ♣ 三级标题 👈

👉 ♦ 四级标题 👈


♠ 曲面细分

在第三章管线的学习当中我们已经对细分曲面阶段有了一定的了解,这一章节我们在对其进行一遍系统一点的学习

细分曲面位于顶点着色器和几何着色器之间,分为了三个阶段分别是曲面细分控制着色器(TCS)、固定功能型曲面细分引擎以及曲面细分评估着色器(TES)

曲面细分控制着色器负责生成3项数据

  • 生成单个面片的内外曲面细分因子
  • 生成单个输出控制点的位置和其他属性
  • 生成单个面片的用户定义的变量

曲面细分引擎将确定大基元如何拆分成小基元

曲面细分评估着色器接受上二者传递的数据、处理后输出至基元装配

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分


♥ 曲面细分基元模式

曲面细分模式用于确定怎么拆分基元的,拆分的方式有三种分别是四边形、三角形或等值线,下面我们挨个看个例子

注:以下所有示例均摘自OpenGL超级宝典配套资源代码tessmodes,可自行查看

注:以下示例均设置默认顶点和片元着色器,文中不在累述

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分
OpenGL超级宝典第八章学习笔记:基元处理之曲面细分


♣ 使用四边形拆分基元

下方是一个简单的使用四边形拆分基元的曲面细分控制着色器和曲面细分评估着色器的例子

  • 曲面细分控制着色器
# version 420 core

layout (vertices = 4) out;

void main(void)                                                               
{                                                                             
    if(gl_InvocationID == 0)                                                  
    {                                                                         
        gl_TessLevelInner[0] = 9.0;                                           
        gl_TessLevelInner[1] = 7.0;                                           
        gl_TessLevelOuter[0] = 3.0;                                           
        gl_TessLevelOuter[1] = 5.0;                                           
        gl_TessLevelOuter[2] = 3.0;                                           
        gl_TessLevelOuter[3] = 5.0;                   
    } 
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; 
}                                                                             
  • 曲面细分控制着色器
# version 420 core  
                                                                
layout (quads) in;                                                                   
                                                                
void main(void)                                                                      
{                                             
    vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);       
    vec4 p2 = mix(gl_in[2].gl_Position, gl_in[3].gl_Position, gl_TessCoord.x);       
    gl_Position = mix(p1, p2, gl_TessCoord.y);                                       
}

上述着色器运行后的效果如下图所示

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分

我们简单介绍一下着色器代码中比较重要的部分

要点1:gl_TessLevelInner用来控制内部细分的等级
要点2:gl_TessLevelOuter用来控制外部细分的等级
要点3:layout (quads) in四边形模式的特殊限定符

我们可以很明显的看出来外部边被分成了5-3-5-3,对应着我们上部分gl_TessLevelOuter设置的细分等级

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分

我们也可以很明显的看出来内部被分成了9*7的区域,对应着我们上部分gl_TessLevelInner设置的细分等级

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分


♣ 使用三角形的曲面细分

同理我们先看一下着色器代码和最终的显示效果

  • 曲面细分控制着色器
# version 420 core 
                                                                                  
layout (vertices = 3) out;                                                        
                                                                                  
void main(void)                                                                   
{                                                                                 
    if (gl_InvocationID == 0)                                                     
    {                                                                             
        gl_TessLevelInner[0] = 5.0;                                               
        gl_TessLevelOuter[0] = 8.0;                                               
        gl_TessLevelOuter[1] = 8.0;                                               
        gl_TessLevelOuter[2] = 8.0;                                               
    }                                                                             
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;     
}                                                                                                                                                            
  • 曲面细分控制着色器
# version 420 core 
                                                                                  
layout (triangles) in;                                                            
                                                                                  
void main(void)                                                                   
{                                                                                 
    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +                       
                  (gl_TessCoord.y * gl_in[1].gl_Position) +                       
                  (gl_TessCoord.z * gl_in[2].gl_Position);                        
}                                                                                 

上述着色器运行后的效果如下图所示

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分

我们简单介绍一下着色器代码中比较重要的部分

要点1:gl_TessLevelInner数组的第一个元素,该级别应用于曲面细分三角形的整个内部区域
要点2:gl_TessLevelOuter数组的前三个元素用于设置三角形三条边的曲面细分因子
要点3:layout (triangles) in三角形模式的特殊限定符

我们可以很明显的看出来三条边都被分成了8分,对应着我们上部分gl_TessLevelOuter设置的细分等级

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分

下图依次展示了gl_TessLevelInner内部细分等级2-5的效果,细分等级越大,内部细分的越复杂

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分


♣ 使用等值线的曲面细分

同理我们先看一下着色器代码和最终的显示效果

  • 曲面细分控制着色器
# version 420 core  
                                                                                    
layout (vertices = 4) out;                                                          
                                                                                    
void main(void)                                                                     
{                                                                                   
    if (gl_InvocationID == 0)                                                       
    {                                                                               
        gl_TessLevelOuter[0] = 5.0;                                                 
        gl_TessLevelOuter[1] = 5.0;                                                 
    }                                                                               
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;       
}                                                                                                                                                                           
  • 曲面细分控制着色器
# version 420 core  
                                                                                     
layout (isolines) in;                                                                
                                                                                     
void main(void)                                                                      
{                                                                                    
    float r = (gl_TessCoord.y + gl_TessCoord.x / gl_TessLevelOuter[0]);              
    float t = gl_TessCoord.x * 2.0 * 3.14159;                                        
    gl_Position = vec4(sin(t) * r, cos(t) * r, 0.5, 1.0);                            
}                                                                                                                                                                   

上述着色器运行后的效果如下图所示

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分

我们简单介绍一下着色器代码中比较重要的部分

要点1:gl_TessLevelInner不在使用
要点2:gl_TessLevelOuter的前两个分量中的两个外部曲面细分因子分别用于确定线条数量以及每条线上的线段数量
要点3:layout (isolines) in等值线模式的特殊限定符


♣ 曲面细分点模式

使用point_model布局限定符,可将生成的顶点按照独立点进行渲染

  • 曲面细分控制着色器
# version 420 core   
                                                                                  
layout (triangles, point_mode) in;                                                
                                                                                  
void main(void)                                                                   
{                                                                                 
    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +                       
                  (gl_TessCoord.y * gl_in[1].gl_Position) +                       
                  (gl_TessCoord.z * gl_in[2].gl_Position);                        
}                                                                                                      

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分


♥ 曲面细分子分段模式

在一定情况下我们可以调整对已生成基元的边缘的分段方式,下面介绍一下几种分段方式的效果和特定布局限定符

♣ 等间距模式

使用限定符equal_spacing,在着色器中的写法如下,效果就是边缘等分,如下图

layout (triangles, equal_spacing) in; 

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分


♣ 分段长度模式

使用限定符fractional_even_spacingfractional_odd_spacing,在着色器中的写法如下,效果就是根据情况对边缘进行不等分,如下图

layout (triangles, fractional_even_spacing) in; 

layout (triangles, fractional_odd_spacing) in; 

OpenGL超级宝典第八章学习笔记:基元处理之曲面细分
OpenGL超级宝典第八章学习笔记:基元处理之曲面细分


♣ 控制环绕顺序

使用以下布局限定符指定顺时针环绕顺序

layout (cw) in;

要指定曲面细分引擎所生成的基元环绕顺序是逆时针,需要添加此限定符

layout (ccw) in;

♥ 数据在曲面细分着色器之间的传递

曲面细分控制着色器的输入和输出都用数组表示,输入数组的尺寸根据每个面片中的控制点数量确定,通过调用以下函数设置

glPatchParameteri(GL_PATCH_VERTICES,n);

注:表示每个面片的顶点数量。默认情况下,每个面片的顶点数量为3

曲面细分控制着色器的输出也是数组,但其尺寸通过着色器前方的顶点输出布局限定符设置

某些简单的渲染流程可以不包含曲面细分控制着色器,当不存在曲面细分控制着色器时,所有内外部曲面细分等级的默认值为1.0。可通过调用glPatchParameterfv()更改此设置,其原型为

void glPatchParameterfv (GLenum pnameconst GLfloat * values);

♠ 推送

  • Github
https://github.com/KingSun5

♠ 结语

若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。文章来源地址https://www.toymoban.com/news/detail-471612.html

👉 本文属于原创文章,转载请评论留言,并在转载文章头部著名作者出处👈

到了这里,关于OpenGL超级宝典第八章学习笔记:基元处理之曲面细分的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 自然语言处理: 第八章chatGPT的搭建

    Transformer 大模型家族可以分成三类, 至于三者的区别可以参考上一章: Encoder-only, Decoder-only, 只需要Pre_train Encoder-decoder , 可以在一些任务上无需进行fine_tune 必须要在下游任务进行微调比如Bert , Bart 。 T5 这种无需要微调就能完成一些任务 。最后GPT从3开始,只需要预训练就能适

    2024年02月12日
    浏览(45)
  • javacv从入门到精通进阶——第八章:视频流处理

    JavaCV提供了使用FFmpeg对视频流进行处理和推送的功能。下面是使用JavaCV进行视频流处理和推送的一般步骤: 创建FFmpegFrameGrabber并设置输入URL: 创建FFmpegFrameRecorder并设置输出URL、宽度和高度: 通过grabber.grabImage()逐帧抓取视频流: 最后,通过grabber.stop()和recorder.stop()停止处理

    2023年04月13日
    浏览(55)
  • 华为HCIA笔记第八章 VLAN原理和配置

    默认情况下交换机所有接口属于一个广播域(局域网) 网络规模的增加,多个交换机互联,广播域变得越来越大,造成以下问题: 广播泛滥 安全风险 设备性能下降 VLAN技术将一个大的广播域划分成多个小的广播域 8.2.1 实现方式 在数据帧中插入VLAN Tag 形成802.1Q帧: 数据帧结

    2024年01月25日
    浏览(41)
  • OBCP第八章 OB运维、监控与异常处理-日常运维操作

    白屏: 集群、Zone、Observer 常用运维操作  常用运维操作 运维场景 步骤 时钟同步 OceanBase从Partition的多个副本中选出主对外提供服务。为避免Paxos的活锁问题,OceanBase 采用一种基于时钟的选举算法选主 检查 NTP 状态:运行 ntpstat 检查 NTP 服务器状态。如果结果为 synchronised to

    2023年04月08日
    浏览(44)
  • 【Rust】Rust学习 第八章常见集合

    Rust 标准库中包含一系列被称为  集合 ( collections )的非常有用的数据结构。大部分其他数据类型都代表一个特定的值,不过集合可以包含多个值。不同于内建的数组和元组类型,这些集合指向的数据是储存在堆上的,这意味着数据的数量不必在编译时就已知,并且还可以随

    2024年02月13日
    浏览(43)
  • 系统集成项目管理工程师 笔记(第八章:项目进度管理)

    项目进度管理包括为管理项目按时完成所需的7个过程,具体为: (1) 规划进度管理 过程:制定政策、程序和文档以管理项目进度。 (2) 定义活动 过程:识别和记录为完成项目可交付成果而需采取的具体行动。 (3) 排列活动顺序 过程:识别和记录项目活动之间的关系。

    2023年04月25日
    浏览(68)
  • 统计学习导论(ISLR) 第八章树模型课后习题

    🌸个人主页:JOJO数据科学 📝个人介绍: 统计学top3 高校统计学硕士在读 💌如果文章对你有帮助,欢迎✌ 关注 、👍 点赞 、✌ 收藏 、👍 订阅 专栏 ✨本文收录于【R语言数据科学】 本系列主要介绍R语言在数据科学领域的应用包括: R语言编程基础、R语言可视化、R语言进

    2024年02月12日
    浏览(38)
  • (数字图像处理MATLAB+Python)第八章图像复原-第一、二节:图像复原概述和图像退化模型

    图像复原 :在图像生成、记录、传输过程中,由于成像系统、设备或外在的干扰,会导致图像质量下降,称为 图像退化 ,如大气扰动效应、光学系统的像差、物体运动造成的模糊、几何失真等。图像复原是指通过使用图像处理技术来恢复受损图像的原始信息,使其尽可能接

    2024年02月12日
    浏览(72)
  • (数字图像处理MATLAB+Python)第八章图像复原-第五、六节:盲去卷积复原和几何失真校正

    盲去卷积复原 :当我们考虑图像复原中的盲去卷积复原时,我们可以使用以下数学符号和方程来描述该问题 原始图像 :我们用I表示原始图像,其中I是一个二维离散函数。 I ( x , y ) I(x, y) I ( x , y ) 表示在坐标 ( x , y ) (x, y) ( x , y ) 处的图像强度值 模糊核 :我们用 H H H 表示未

    2024年02月04日
    浏览(59)
  • 第八章:L2JMobius学习 – 游戏服务GameServer讲解

    本章节我们来讲解GameServer服务,首先来查看它的文件结构 接下来,我们还是先研究network网络数据通信部分。 接下来,我们介绍GameServer与玩家客户端之间的通信。当我们启动GameServer服务的时候,他会启动一个NetServer服务类,这个类我们之前已经讲过了。它里面有一个Server

    2024年02月13日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包