《UnityShader入门精要》学习1

news2024/12/23 11:04:56

读者可以在开源网站github(https://github.com/candycat1992/Unity_Shaders_Book)上下载本书的源代码。

第二章 渲染流水线

渲染流水线的最终目的在于生成或者说是渲染一张二维纹理,即我们在电脑屏幕上看到的所有效果,它的输入是一个虚拟摄像机,一些光源,一些 Shader 以及纹理

Shader 仅仅是渲染流水线的一个环节

一个渲染流程分成3个阶段:应用阶段(Application Stage)、几何阶段(Geometry Stage)、光栅化阶段(Rasterizer Stage)。

应用阶段

由应用主导,通常由CPU负责

这个阶段主要任务是:对渲染数据进行粗颗粒剔除,向下阶段输出渲染图元,并设置渲染状态(主要是设置着色器,设置测试开关和参数)

视锥体:是指场景中摄像机的可见的一个锥体范围。它有上下左右近远,共6个面组成。在视锥体内的景物可见,反之则不可见。为了提高性能,只对其中与视锥体有交集的对象进行绘制

CPU可以做粗粒度剔除(culling),包括视锥体剔除(Frustum Culling)和遮挡剔除( Occlusion Culling)两种,这样可以剔除不可见的物体,减少无效数据,移交给GPU的数据更精简。CPU做的粗粒度剔除是物体层面的。

漫反射,是投射在粗糙表面上的光向各个方向反射的现象。当一束平行的入射光线射到粗糙的表面时,表面会把光线向着四面八方反射,所以入射线虽然互相平行,由于各点的法线方向不一致,造成反射光线向不同的方向无规则地反射,这种反射称之为“漫反射”或“漫射”,这种反射的光称为漫射光。很多物体,如植物、墙壁、衣服等,其表面粗看起来似乎是平滑,但用放大镜仔细观察,就会看到其表面是凹凸不平的,所以本来是平行的太阳光被这些表面反射后,弥漫地射向不同方向。漫反射的每条光线均遵循反射定律。
 

几何阶段

这一阶段通常在GPU上进行

几何阶段的一个重要任务就是把顶点坐标变换到屏幕空间中,再交给光栅器进行处理。通过对输入的渲染图元进行多步处理后,这一阶段将会输出屏幕空间的二维顶点坐标、每个顶点对应的深度值、着色等相关信息,并传递给下一个阶段。

由顶点着色器处理,主要是平移,旋转和缩放三种坐标变换,通过矩阵运算实现。
在几何阶段执行的Shader叫顶点着色器,在光栅化阶段执行的Shader叫片元着色器。
 

光栅化阶段

这一阶段将会使用上个阶段传递的数据来产生屏幕上的像素,并渲染出最终的图像。这一阶段也是在GPU上运行。光栅化的任务主要是决定每个渲染图元中的哪些像素应该被绘制在屏幕上。它需要对上一个阶段得到的逐顶点数据(例如纹理坐标、顶点颜色等)进行插值,然后再进行逐像素处理。

CPU 与 GPU 之间的通信

渲染流水线的起点是CPU,即应用阶段。应用阶段大致可分为下面3个阶段:

(1)把数据加载到显存中。(2)设置渲染状态。(3)调用Draw Call

把数据加载到显存中

所有渲染所需的数据都需要从硬盘(Hard Disk Drive, HDD)中加载到系统内存(Random Access Memory, RAM)中。然后,网格和纹理等数据又被加载到显卡上的存储空间——显存(Video Random Access Memory, VRAM)中

显卡对于显存的访问速度更快,而且大多数显卡对于RAM没有直接的访问权利。

开发者还需要通过CPU来设置渲染状态,从而“指导”GPU如何进行渲染工作。

设置渲染状态

什么是渲染状态呢?一个通俗的解释就是,这些状态定义了场景中的网格是怎样被渲染的。

调用 Draw Call

Draw Call就是一个命令,它的发起方是CPU,接收方是GPU。这个命令仅仅会指向一个需要被渲染的图元(primitives)列表

当给定了一个Draw Call时,GPU就会根据渲染状态(例如材质、纹理、着色器等)和所有输入的顶点数据来进行计算,最终输出成屏幕上显示的那些漂亮的像素

GPU 流水线

GPU渲染的过程就是GPU流水线。

几何阶段:顶点着色器(必须编程) - 曲面细分着色器(可选可编程) - 几何着色器(可选可编程) - 裁剪(可配置)- 屏幕映射(不能控制)
光栅化阶段:三角形设置(不能控制) - 三角形遍历(不能控制) - 片元着色器(可选可编程) - 逐片元操作(可配置)
 

顶点着色器(Vertex Shader)是完全可编程的,它通常用于实现顶点的空间变换、顶点着色等功能。曲面细分着色器(Tessellation Shader)是一个可选的着色器,它用于细分图元。几何着色器(Geometry Shader)同样是一个可选的着色器,它可以被用于执行逐图元(Per-Primitive)的着色操作,或者被用于产生更多的图元。下一个流水线阶段是裁剪(Clipping),这一阶段的目的是将那些不在摄像机视野内的顶点裁剪掉,并剔除某些三角图元的面片。这个阶段是可配置的。例如,我们可以使用自定义的裁剪平面来配置裁剪区域,也可以通过指令控制裁剪三角图元的正面还是背面。几何概念阶段的最后一个流水线阶段是屏幕映射(Screen Mapping)。这一阶段是不可配置和编程的,它负责把每个图元的坐标转换到屏幕坐标系中。

光栅化概念阶段中的三角形设置(Triangle Setup)和三角形遍历(Triangle Traversal)阶段也都是固定函数(Fixed-Function)的阶段。接下来的片元着色器(Fragment Shader),则是完全可编程的,它用于实现逐片元(Per-Fragment)的着色操作。最后,逐片元操作(Per-Fragment Operations)阶段负责执行很多重要的操作,例如修改颜色、深度缓冲、进行混合等,它不是可编程的,但具有很高的可配置性。

顶点着色器

顶点着色器(Vertex Shader)是流水线的第一个阶段,它的输入来自于CPU。顶点着色器的处理单位是顶点,也就是说,输入进来的每个顶点都会调用一次顶点着色器。顶点着色器本身不可以创建或者销毁任何顶点,而且无法得到顶点与顶点之间的关系。

顶点着色器需要完成的工作主要有:坐标变换和逐顶点光照

我们可以通过改变顶点位置来模拟水面,布料等

一个最基本的顶点着色器必须完成的一个工作是,把顶点坐标从模型空间转换到齐次裁剪空间

裁剪

一个图元和摄像机视野的关系有3种:完全在视野内、部分在视野内、完全在视野外。

图元——图形元素,可以编辑的最小图形单位。图元是图形软件用于操作和组织画面的最基本的素材。
例如,一条线段的一个顶点在视野内,而另一个顶点不在视野内,那么在视野外部的顶点应该使用一个新的顶点来代替,这个新的顶点位于这条线段和视野边界的交点处。

无法通过编程来控制裁剪的过程,而是硬件上的固定操作

屏幕映射

屏幕映射(ScreenMapping)的任务是把每个图元的x和y坐标转换到屏幕坐标系(Screen Coordinates)下。屏幕坐标系是一个二维坐标系,它和我们用于显示画面的分辨率有很大关系。

屏幕坐标系和z坐标一起构成了一个坐标系,叫做窗口坐标系(Window Coordinates)

三角形设置

光栅化阶段有两个最重要的目标:计算每个图元覆盖了哪些像素,以及为这些像素计算它们的颜色。

光栅化的第一个流水线阶段是三角形设置(Triangle Setup),这个阶段会计算光栅化一个三角网格所需的信息

三角形遍历

三角形遍历(Triangle Traversal)阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖的话,就会生成一个片元(fragment)。而这样一个找到哪些像素被三角网格覆盖的过程就是三角形遍历,这个阶段也被称为扫描变换(Scan Conversion)

一个片元并不是真正意义上的像素,而是包含了很多状态的集合,这些状态用于计算每个像素的最终颜色。这些状态包括了(但不限于)它的屏幕坐标、深度信息,以及其他从几何阶段输出的顶点信息,例如法线、纹理坐标等。

片元着色器

。真正会对像素产生影响的阶段是下一个流水线阶段——逐片元操作(Per-Fragment Operations)。

片元着色器的输入是上一个阶段对顶点信息插值得到的结果

它的局限在于,它仅可以影响单个片元

逐片元操作

逐片元操作(Per-Fragment Operations)是OpenGL中的说法,在DirectX中,这一阶段被称为输出合并阶段(Output-Merger)

这一阶段有几个主要任务。

  • (1)决定每个片元的可见性。这涉及了很多测试工作,例如深度测试、模板测试等。
  • (2)如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并,或者说是混合。

                        模板测试和深度测试的简化流程图

什么是 OpenGL/DirectX

OpenGL和DirectX就是这些图像应用编程接口,这些接口用于渲染二维或三维图形。

这些接口架起了上层应用程序和底层GPU的沟通桥梁。一个应用程序向这些接口发送渲染命令,而这些接口会依次向显卡驱动(Graphics Driver)发送渲染命令,这些显卡驱动是真正知道如何和GPU通信的角色,正是它们把OpenGL或者DirectX的函数调用翻译成了GPU能够听懂的语言,同时它们也负责把纹理等数据转换成GPU所支持的格式。一个比喻是,显卡驱动就是显卡的操作系统。图2.18显示了这样的关系

 什么是HLSL、GLSL、CG

着色语言(Shading Language)。着色语言是专门用于编写着色器的,常见的着色语言有DirectX的HLSL(High Level Shading Language)、OpenGL的GLSL(OpenGL Shading Language)以及NVIDIA的CG(C for Graphic)。HLSL、GLSL、CG都是“高级(High-Level)”语言,但这种高级是相对于汇编语言来说的,而不是像C#相对于C的高级那样。这些语言会被编译成与机器无关的汇编语言,也被称为中间语言(Intermediate Language, IL)。这些中间语言再交给显卡驱动来翻译成真正的机器语言,即GPU可以理解的语言。

什么是Draw Call

Draw Call本身的含义很简单,就是CPU调用图像编程接口

Draw Call中造成性能问题的元凶是GPU,认为GPU上的状态切换是耗时的,其实不是的,真正“拖后腿”其实的是CPU。

问题一:CPU和GPU是如何实现并行工作的?

我们需要让CPU和GPU可以并行工作。而解决方法就是使用一个命令缓冲区(Command Buffer)。

命令缓冲区中的命令有很多种类,而Draw Call是其中一种,其他命令还有改变渲染状态等(例如改变使用的着色器,使用不同的纹理等)

问题二:为什么Draw Call多了会影响帧率?

GPU的渲染能力是很强的,渲染200个还是2000个三角网格通常没有什么区别,因此渲染速度往往快于CPU提交命令的速度。如果Draw Call的数量太多,CPU就会把大量时间花费在提交Draw Call上,造成CPU的过载。

问题三:如何减少Draw Call?

批处理(Batching)

在游戏开发过程中,为了减少Draw Call的开销,有两点需要注意。

  • (1)避免使用大量很小的网格。当不可避免地需要使用很小的网格结构时,考虑是否可以合并它们。
  • (2)避免使用过多的材质。尽量在不同的网格之间共用同一个材质。

什么是固定管线渲染

固定函数的流水线(Fixed-Function Pipeline),也简称为固定管线,通常是指在较旧的GPU上实现的渲染流水线

所以,Shader 是什么

  • GPU流水线上一些可高度编程的阶段,而由着色器编译出来的最终代码是会在GPU上运行的(对于固定管线的渲染来说,着色器有时等同于一些特定的渲染设置)
  • 有一些特定类型的着色器,如顶点着色器、片元着色器等;
  • ·依靠着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换以及传递数据,用片元着色器来进行逐像素的渲染

 

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

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

相关文章

微软警告国家级黑客正在利用关键的Atlassian Confluence漏洞

导语:近日,微软发布警告称,国家级黑客组织正在利用Atlassian Confluence的关键漏洞进行攻击。该漏洞已被微软追踪到一个名为Storm-0062(又称DarkShadow或Oro0lxy)的黑客组织。微软的威胁情报团队表示,他们自…

三次挥手和四次握手

TCP建立连接(三次握手) 经过DNS域名解析后,获取到了服务器的IP地址,在获取到IP地址后,便会开始建立一次连接,这是由TCP协议完成的,主要通过三次握手进行连接。 第一次握手: 建立连…

MySQL 2 环境搭建(MySQL5.7.43和8.0.34的下载;8.0.34的安装、配置教程 )

目录 MySQL的下载、8.0.34的安装及配置 1 MySQL版本介绍 2 MySQL 下载 1. 下载地址 2. 打开官网,点击DOWNLOADS ​编辑 3. 点击 MySQL Community Server 4. 在General Availability(GA) Releases中选择适合的版本 5.下载8.0.34和5.7.43版本 3 MySQL8.0 …

数据集笔记:分析OpenCellID 不同radio/ create_time update_time可视化

1 读取数据 (以新加坡的cellID为例) import geopandas as gpd import pandas as pdopencellidpd.read_csv(OpenCellID_SG.csv,headerNone,names[radio,mcc,net,area,cell,unit,lon,lat,range,samples,changeable1,created1,updated,AveSignal]) opence…

2024届通信工程保研经验分享(预推免入营即offer)

2024届通信工程保研经验分享(预推免入营即offer) BackGround夏令营情况:预推免情况: BackGround 本科院校:末九 专业:通信工程 rank:3/123(预推免绩点排名)&#xff0…

我用了多年的前端框架,强烈推荐!

大家好,我是鱼皮,今天给大家分享一个我自己用了多年、现在团队也在用的前端框架 —— Ant Design Pro。 什么是 Ant Design Pro? Ant Design Pro 是由蚂蚁金服开发的、基于 Ant Design 组件库的开发框架,专门用于构建企业级管理…

Linux:redis集群(3.*版本 和 5.*版本)搭建方法

介绍 至少6个实例才能组成集群。3主3从会自动分配 Redis集群原理 Redis集群架构 Redis Cluster采用虚拟槽分区,将所有的数据根据算法映射到0~16383整数槽内 Redis Cluster是一个无中心的结构 每个节点都保存数据和整个集群的状态 集群角色 Master:Master…

docker入门加实战—docker常见命令

docker入门加实战—docker常见命令 在介绍命令之前,先用一副图形象的展示一下docker的命令: 常见命令 docker的常见命令和文档地址如下表: 命令说明文档地址docker pull拉取镜像docker pulldocker push推送镜像到DockerRegistrydocker pus…

c/c++--字节对齐(byte alignment)

1. 默认字节对齐 在所有结构体成员的字节长度都没有超出操作系统基本字节单位(32位操作系统是4,64位操作系统是8)的情况下 按照结构体中字节最大的变量长度来对齐;若结构体中某个变量字节超出操作系统基本字节单位 那么就按照系统字节单位来对齐。 注意&#xff1…

MQTT C库下载

方法一、从Eclipse paho下载 https://eclipse.dev/paho/index.php?pagedownloads.php 方法二,从MQTT官网下载 https://mqtt.org/software/ https://os.mbed.com/teams/mqtt/code/MQTTPacket/ MQTTPacket源码和paho下载的差不多 方法三、从Keil5 包管理工具…

刷新页面,时间展示错误

当我们刷新页面之前时间是正常展示的,在刷新页面之后,时间也在展示,只不过时间错误。 刷新之前 刷新之后(系统原因暂时拿不到数据):用同一图代替,颜色是灰色 明显可以看到时间颜色发生了变化&a…

C++智能指针(二)——weak_ptr初探

文章目录 1. shared_ptr 存在的问题2. 使用weak_ptr2.1 初始化 weak_ptr2.2 访问数据 1. shared_ptr 存在的问题 与 shared_ptr 的引入要解决普通指针存在的一些问题一样,weak_ptr 的引入,也是因为 shared_ptr 本身在某些情况下,存在一些问题…

android U广播详解(一)

概念介绍 进程队列 BroadcastQueueModernImpl 的设计围绕着为设备上的每个潜在进程维护一个单独的 BroadcastProcessQueue 实例。表明用于传送到特定进程的Pending {link BroadcastRecord} 条目队列。整个类都标记为 {code NotThreadSafe},因为调用者有责任始终与…

Linux 用户层、内核层和MMU

一、Linux 用户层、内核层 在 Linux 中,所有设备都以文件的形式存放在/dev 目录下,都是通过文件的方式进行访问,设备节点是Linux 内核对设备的抽象,一个设备节点就是一个文件。应用程序通过一组标准化的调用执行访问设备&#xff…

SwiftUI 中如何实现文件导入和导出

文章目录 前言导入导出文件移动总结 前言 之前谈论了在 SwiftUI 中选择照片和视频的问题。今天我们将学习如何在 SwiftUI 视图中导入和导出文件。通过使用新的 fileImporter 和 fileExporter 视图修饰符,可以很方便实现这个功能。 导入 SwiftUI 框架提供了 fileI…

RAMday9

设置按键中断,按键1按下,LED亮,再按一次,灭;按键2按下,蜂鸣器响,再按一次,不响;按键3按下,风扇转,再按一次,风扇停 代码 do_irq.c #include "key.h" extern…

火狐浏览器页面翻译

打开扩展 扩展搜索tran 点击谷歌快译组件 设置翻译语言 安装完成后即可右键翻译页面

【数据库——MySQL(实战项目1)】(3)图书借阅系统——存储函数

目录 1. 简述2. 功能代码2.1 创建存储函数,根据图书编号查借阅人姓名,并调用该函数查询‘ **小邓在森林** ’已借未还的图书情况;2.2 创建存储函数,计算某借阅人还能借阅的图书数目,学生限额 5 本,教师限额…

两个连续变量乘积线性化——McCormick envelope近似

两个连续变量乘积的形式,可以进行近似线性化转化(没有完全等价的线性化方法)。要说明的是这是一种近似线性化,并不是完全等价,存在一定的误差。转化的方法是,McCormick envelope近似(McCormick …

快速解决“找不到msvcr120.dll无法执行代码”问题,总结5解决方法

计算机已经成为我们生活和工作中不可或缺的一部分。然而,在使用计算机的过程中,我们常常会遇到各种问题,其中之一就是找不到msvcr120.dll文件。这个问题可能会可能导致计算机程序软件,游戏无法正常运行,影响到我们的工…