图形学中一些基本知识的总结与复习

前言
在过完games101课程后仍然觉得自己还有许多地方不懂与遗漏,以此来补充与复习一些其中的知识。
参考:Games101、《Unity Shader 入门精要》

GPU渲染流水线(GPU Rendering Pipeline)

l流程图(来自知乎“拓荒犬”)
----注:Games101课程中所展示渲染流程与书中有所不同,大体相同,细节展示有所不同,这点请看图在这里插入图片描述

这里以《Unity Shader入门精要》中为主介绍,如下图:
在这里插入图片描述
补充:绿色表示完全可编程控制,黄色表示可以配置但不是可编程,蓝色表示由CPU固定实现。实线表示该Shader必须由开发者编程实现,虚线表示该Shader是可选的。

----------------------下面说明各阶段:

Application(应用阶段):

渲染流水线的起点是CPU,即应用阶段。应用阶段大致可分为以下3个阶段:
(1)把数据加载到显存中
(2)设置渲染状态
(3)调用Draw Call

> 把数据加载到显存中:
渲染所需要的数据需要从硬盘传输到系统内存中(RAM),网格和纹理等数据被加载到显存中。(真实渲染中需要加载到显存中的数据还有顶点的位置信息、法线方向、顶点颜色、纹理坐标等)。
> 设置渲染状态:
渲染状态可以理解为场景中的网格是怎样被渲染的,即使用哪个顶点着色器/片元着色器、光源属性、材质等。如果没有更改渲染状态的话那么所有网格都将使用同一种渲染状态。
下图为同一状态下渲染3个网格。
在这里插入图片描述
接下来,就是调用Draw Call啦!

> 调用Draw Call:
其实Draw Call本质上就是一个命令,它的发起方是CPU,接收方是GPU。当我们给定了一个Draw Call时,GPU就会根据渲染状态(例如材质、纹理、着色器等)和所有输入的顶点数据来进行计算。

----------关于Draw Call的一些补充----------
Draw Call本身的含义很简单,就是CPU调用图像编程接口,入OpenGL中的glDrawElements命令。有一个常见的误区时Draw Call中造成性能问题的元凶时GPU,认为GPU上的状态切换是耗时的,其实真正“拖后腿”的是CPU
问题一:CPU和GPU是如何实现并行工作的?
若没有流水线化,则CPU需要等GPU完成上一个渲染任务才能再次发送渲染命令,这导致效率低下。而解决方法就是使用一个“命令缓冲区
命令缓冲区包含了一个命令队列,CPU向其中添加命令,GPU从中读取命令,CPU与GPU互不干扰。如下图:
在这里插入图片描述
(黄色方框内的命令就是Draw Call,而红色方框内的命令用于改变渲染状态。使用红色方框来表示改变渲染状态的命令,是因为这些命令往往更加耗时)

问题二:为什么Draw Call多了会影响帧率
在每次调用Draw Call之前,CPU需要向GPU发送很多内容,包括数据、状态和命令等。在这一阶段,CPU需要完成很多工作,例如检查渲染状态等。当CPU完成这些准备工作之后GPU就可以开始本次渲染了。但是由于GPU的渲染能力很强,会导致GPU的渲染速度大于CPU提交命令的速度。如果Draw Call的数量太多,CPU就会把大量时间花费在提交Draw Call上,造成CPU的过载。如下图:
在这里插入图片描述
(虚线框表示GPU已经完成的命令。此时命令缓冲区已没有可执行的命令,GPU处于空闲状态,而CPU还没有准备好下一个渲染命令。)

问题三:如何减少Draw Call
这里仅提一种方法,叫做“批处理” 方法。
提交大量很小的Draw Call会造成CPU的性能瓶颈,即CPU把时间都花费在准备Draw Call的工作上了。批处理的思想是把很多小的Draw Call合并成一个大的Draw Call。 (批处理技术更适合于那些静态的物体。)

Geometry Processing(几何阶段):

几何阶段又细分为以下几个阶段:
(1)顶点着色器
(2)曲面细分着色器
(3)几何着色器
(4)裁剪
(5)屏幕映射

>顶点着色器:
顶点着色器(Vertex Shader)是完全可编程的,顶点着色器本身不可以创建或者销毁任何顶点,而且无法得到顶点与顶点之间的关系。顶点着色器的主要工作:坐标变换和逐顶点光照。如下图在这里插入图片描述

  • 坐标变换:在顶点着色器中完成MVP变换,把顶点坐标从模型空间转换到齐次裁剪空间。接着通常再由硬件做透视除法,最终得到NDC。

>曲面细分着色器:
一个可选着色器,用于细分图元。

>几何着色器:
一个可选着色器,用于逐图元的着色操作,或者用于产生更多的图元。

>裁剪:
裁剪提出的目的是要为了处理掉那些不在摄像机视野范围内的物体。由于我们已知在NDC下的顶点位置,即顶点位置在一个立方体内,则只需要将图元裁剪到单位立方体内,如下图
在这里插入图片描述
图片补充:和单位立方体相交的图元会被裁剪,新的顶点会被生成,原来在外部的顶点会被舍弃。

>屏幕映射:
屏幕映射的任务是把每个图元的x和y坐标转换到屏幕坐标系下。这个过程实际是一个缩放的过程,但是屏幕映射不会对输入的z坐标做任何处理。过程如下图:
在这里插入图片描述
一些补充:在OpenGL中,屏幕左下角为最小的窗口坐标值,在DirectX中,屏幕的左上角为最小的窗口坐标值。

Rasterization(光栅化阶段):

光栅化阶段细分为以下几个阶段:
(1)三角形设置
(2)三角形遍历
(3)片元着色器
(4)逐片元操作

>三角形设置:
这是光栅化的第一个流水线阶段。上一个阶段输出的都是三角网格的顶点,为了得到整个三角网格对像素的覆盖情况,我们还需计算每条边上的像素坐标。为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表示方式。这样一个计算三角网格表示数据的过程就叫做三角形设置。

>三角形遍历:
这个阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖,则生成一个片元。这个阶段也被称为扫描变换
这一阶段还会根据三角网格3个顶点信息对整个覆盖区域的像素进行插值(利用重心坐标)。如下图(一个简化的计算过程):
在这里插入图片描述
这一步的输出得到一个片元序列。但是一个片元并不是真正意义上的像素,而是包含了很多状态的集合,用于计算每个像素的最终颜色。

>片元着色器:
片元着色器(Fragment Shader)是另一个可编程着色器阶段,又叫做像素着色器(Pixel Shader)。片元着色器的输入是上一个阶段对顶点信息插值得到的结果,而它的输出是一个或者多个颜色值。
前面的光栅化戒定慧产生一系列的数据信息,用来表述一个三角网格是怎天覆盖每个像素的。而每个片元就负责存储这样一系列数据。
如下图:
在这里插入图片描述
这一阶段可以完成许多重要的渲染技术如纹理采样。
局限:它仅可以影响单个片元,当执行片元着色器时,它不可以将自己的任何结果直接发送给它的邻居们。

>逐片元操作:
这是真正会对像素产生影响的一个流水线阶段。
这一阶段会有几个主要任务
<1>进行测试工作,如深度测试、模板测试等。
<2>如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并,或者说是混合。下图是简化后的逐片元操作所做的操作。
在这里插入图片描述

在逐片元操作中的后面的合并操作时,对于不透明物体,开发者可以关闭**混合(Blend)**操作。这样片元着色器计算得到的颜色值就会直接覆盖掉颜色缓冲区的像素值。对于半透明物体,就需要使用混合操作来让这个物体看起来是透明的。


《Unity Shader入门精要》中前面部分对渲染管线的介绍到此结束。下面是一些额外补充:

  1. 不同的文章对渲染管线的阶段分配介绍各有不同,清楚大体过程即可。
  2. 系统为了避免我们看到那些正在进行光栅化的图元,GPU会使用双重缓冲(Double Buffering)也就是说,对场景的渲染发生在幕后,即后置缓冲(Back Buffering)中。一旦场景已经被渲染到了后置缓冲中,GPU就会交换后置缓冲和前置缓冲(Front Buffering)
  3. 鉴于自己总是弄混顶点着色器的作用,在此再次总结一下:顶点着色器中完成MVP变换将顶点变换至齐次裁剪空间中,再由硬件做透视除法得到NDC。接着再由系统做裁剪以及屏幕映射。

下面再放上一些在Games101中渲染管线的图方便作对比:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
写在最后:尽管写了不少,中间仍然可能会出现错误,后面继续学习发现错误后加以改正。
初次写于2023.10.7

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/96957.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

javaWeb网上购物系统的设计与实现

摘 要 随着计算机网络技术的飞速发展和人们生活节奏的不断加快&#xff0c;电子商务技术已经逐渐融入了人们的日常生活当中&#xff0c;网上商城作为电子商务最普遍的一种形式&#xff0c;已被大众逐渐接受。因此开发一个网上商城系统&#xff0c;适合当今形势&#xff0c;更加…

详解FreeRTOS:FreeRTOS任务恢复过程源码分析(进阶篇—4)

本篇博文讲解FreeRTOS中任务恢复过程的源代码,帮助各位更好理解恢复任务的原理和流程。 在详解FreeRTOS:FreeRTOS任务管理函数(基础篇—11)中,讲述了任务恢复函数有两个vTaskResume()和xTaskResumeFromISR(),一个是用在任务中的,一个是用在中断中的,但是基本的处理过程…

智慧空调插座:智控生活好伴侣,节能降耗好帮手

所谓“智能插座”&#xff0c;就是在普通插座上增加Wi-Fi模块&#xff0c;通过手机APP控制单个或整个插座的电源通断&#xff0c;并统计一段时间的用电量。 目前市面上所销售的智能插座&#xff0c;大多具备可连接Wi-Fi网路功能&#xff0c;如此一 来便不需要额外再购买定时控…

评价指标篇——IOU(交并比)

什么是IoU(Intersection over Union) IoU是一种测量在特定数据集中检测相应物体准确度的一个标准。 即是产生的候选框&#xff08;candidate bound&#xff09;与原标记框&#xff08;ground truth bound&#xff09;的交叠率 即它们的交集与并集的比值。最理想情况是完全重叠…

数据中台实战(11)-数据中台的数据安全解决方案

0 微盟删库跑路 除了快、准和省&#xff0c;数据中台须安全&#xff0c;避免“微盟删库跑路”。 2020年2月23日19点&#xff0c;国内最大精准营销服务商微盟出现大面积系统故障&#xff0c;旗下300万商户线上业务全停&#xff0c;商铺后台所有数据被清。始作俑者是一位运维&a…

秒验:可以自定义UI的一键登录服务

一键登录如今成为越来越多移动应用的首选&#xff0c;但千篇一律的登陆界面在引发用户担忧其安全性的同时&#xff0c;也容易让用户在不同APP切换时产生误解。因此&#xff0c;由国内知名移动应用开发服务商MobTech打造的一键登录工具——秒验&#xff0c;通过允许开发者自定义…

C#学习系列相关之多线程(一)----常用多线程方法总结

一、多线程的用途 在介绍多线程的方法之前首先应当知道什么是多线程&#xff0c; 在一个进程内部可以执行多个任务&#xff0c;而这每一个任务我们就可以看成是一个线程。是程序使用CPU的基本单位。进程是拥有资源的基本单位&#xff0c; 线程是CPU调度的基本单位。多线程的作用…

快速掌握批量合并视频

在日常的工作和生活中&#xff0c;我们经常需要对视频进行编辑和处理&#xff0c;而合并视频、添加文案和音频是其中常见的操作。如何快速而简便地完成这些任务呢&#xff1f;今天我们介绍一款强大的视频编辑软件——“固乔智剪软件”&#xff0c;它可以帮助我们轻松实现批量合…

C++深入学习part_1

Linux下编译C程序 安装g命令&#xff1a;sudo apt install g 编译命令&#xff1a;$ g *.cc 或者 *.cpp -o fileName; hellworld 编译程序可以看到&#xff1a; namespace命名空间 首先&#xff0c;命名空间的提出是为了防止变量重名冲突而设置的。 浅浅试一下&#xff1…

深度学习基础之参数量(3)

一般的CNN网络的参数量估计代码 class ResidualBlock(nn.Module):def __init__(self, in_planes, planes, norm_fngroup, stride1):super(ResidualBlock, self).__init__()print(in_planes, planes, norm_fn, stride)self.conv1 nn.Conv2d(in_planes, planes, kernel_size3, …

后端解决跨域(极速版)

header(Access-Control-Allow-Origin: *); header(Access-Control-Allow-Methods:*); 代表接收全部的请求&#xff0c;"POST,GET"//允许访问的方式 指定域&#xff0c;如http://172.20.0.206//宝塔的域名&#xff0c;注意不是&#xff1a;http://wang.jingyi.icu等…

网络和系统操作命令

目录 ping&#xff1a;用于检测网络是否通畅&#xff0c;以及网络时延情况。ipconfig&#xff1a;查看计算机的IP参数配置信息&#xff0c;如IP地址、默认网关、子网掩码等信息。netstat&#xff1a;显示协议统计信息和当前TCP/IP网络连接。tasklist&#xff1a;显示当前运行的…

正点原子嵌入式linux驱动开发——U-boot图形化配置及其原理

经过之前对uboot的学习可以知道&#xff1a;uboot可以通过stm32mp15_trusted_defconfig来配置&#xff0c;或者通过文件stm32mp1.h来配置uboot。还有另外一种配置uboot的方法&#xff0c;就是图形化配置&#xff0c;以前的uboot是不支持图形化配置&#xff0c;只有Linux内核才支…

JMeter工具的介绍,安装

一、本文学习目标 1、能知道JMeter的优缺点 2、能掌握JMeter的安装流程 3、能掌握JMeter线程组的设置 4、能掌握JMeter参数化的使用 5、能掌握JMeter直连数据库操作 6、能掌握JMeter的断言. 二、JMeter简介 &#xff08;1&#xff09;Jmeter详细介绍 **JMeter&#xff08;A…

C++递归函数

在本文中&#xff0c;您将学习创建递归函数。调用自身的函数。 调用自身的函数称为递归函数。并且&#xff0c;这种技术称为递归。 递归在C 中如何工作&#xff1f; void recurse() {... .. ...recurse();... .. ... }int main() {... .. ...recurse();... .. ... } 下图显…

基于SSM+Vue的物流管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;VueHTML 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 …

[每日算法 - 阿里机试] leetcode19. 删除链表的倒数第 N 个结点

入口 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/remove-nth-node-from-end…

(面试)谈谈我对C++面向对象特性的理解

&#x1f4af; 博客内容&#xff1a;C读取一行内个数不定的整数的方式 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准前端&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家&…

yolov5 web端部署进行图片和视频检测

目录 1、思路 2、代码结构 3、代码运行 4、api接口代码 5、web ui界面 6、参考资料 7、代码分享 1、思路 通过搭建flask微型服务器后端&#xff0c;以后通过vue搭建网页前端。flask是第一个第三方库。与其他模块一样&#xff0c;安装时可以直接使用python的pip命令实现…

字符串常量池位于JVM哪里

Java6 和6之前&#xff0c;常量池是存放在方法区&#xff08;永久代&#xff09;中的。Java7&#xff0c;将常量池是存放到了堆中。Java8 之后&#xff0c;取消了整个永久代区域&#xff0c;取而代之的是元空间。运行时常量池和静态常量池存放在元空间中&#xff0c;而字符串常…