《UnityShader入门精要》学习1

读者可以在开源网站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.rhkb.cn/news/156099.html

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

相关文章

【网络安全】「漏洞原理」(二)SQL 注入漏洞之理论讲解

前言 严正声明:本博文所讨论的技术仅用于研究学习,旨在增强读者的信息安全意识,提高信息安全防护技能,严禁用于非法活动。任何个人、团体、组织不得用于非法目的,违法犯罪必将受到法律的严厉制裁。 【点击此处即可获…

发送消息时序图

内窥镜消息队列发送消息原理 目的 有一个多线程的Java应用程序,使用消息队列来处理命令 时序图 startumlactor User participant "sendCmdWhiteBalance()" as Controller participant CommandConsumer participant MessageQueueUser -> Controller:…

【数据库】Sql Server数据迁移,处理自增字段赋值

给自己一个目标,然后坚持一段时间,总会有收获和感悟! 在实际项目开发中,如果遇到高版本导入到低版本,或者低版本转高版本,那么就会出现版本不兼容无法导入,此时通过程序遍历创建表和添加数据方式…

开源音乐播放器!

导读音乐是生活的一部分。维基百科关于音乐发展历史的文章有这样一段不错的描述说:“全世界所有的人们,包括哪怕是最孤立、与世隔绝的部落,都会有自己的特色音乐……”好吧,我们开源人就构成了一个部落。我建议我们的“音乐形式”…

TCP/IP(十四)流量控制

一 流量控制 说明: 本文只是原理铺垫,没有用tcpdumpwiresahrk鲜活的案例讲解,后续补充 ① 基本概念 流量控制: TCP 通过接受方实际能接收的数据量来控制发送方的窗口大小 ② 正常传输过程 背景:1、客户端是接收方,服务端是发送方 --> 下载2、假设接收窗…

基于Vue+ELement实现增删改查案例与表单验证

目录 前言 一、增删改查案例的实现 1.查询 2.增加 3.修改 4.删除 5.增删改查效果演示 二、表单验证 1.在官网中找到表单---表单验证 2.定义规则 3.使用规则 前言 Element UI是一款基于Vue.js的组件库,提供了丰富的组件和功能,包括表单、按钮、…

mysql面试题28:MySQL的主从复制模式、MySQL主从复制的步骤、MySQL主从同步延迟的原因、MySQL主从同步延迟的解决办法

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:简单讲一下MySQL的主从复制模式 MySQL的主从复制(Master-Slave Replication)是一种数据库复制技术,用于将一个MySQL数据库服务器(主服务器)的…

nodejs+vue+elementui养老院老年人服务系统er809

“养老智慧服务平台”是运用nodejs语言和vue框架,以MySQL数据库为基础而发出来的。为保证我国经济的持续性发展,必须要让互联网信息时代在我国日益壮大,蓬勃发展。伴随着信息社会的飞速发展,养老智慧服务平台所面临的问题也一个接…

嵌入式面试常见问题(一)

目录 1.什么情况下会出现段错误? 2.swap() 函数为什么不能交换两个变量的值 3.一个函数有六个参数 分别放在哪个区? 4.定义一个变量,赋初值和不赋初值分别保存在哪个区? 5.linux查看端口状态的命令 6.结构体中->和.的区…

uniapp:幸运大转盘demo

<template><view class"index"><image src"../../static/img/158.png" mode"" class"banner"></image><view class"title">绿色积分加倍卡拿到手软</view><almost-lottery :lottery…

使用 L293D 电机驱动器 IC 和 Arduino 控制直流电机

如果您打算组装新的机器人朋友&#xff0c;您最终会想要学习如何控制直流电机。控制直流电机最简单且经济的方法是将 L293D 电机驱动器 IC 与 Arduino 连接。它可以控制两个直流电机的速度和旋转方向。 此外&#xff0c;它还可以控制单极步进电机&#xff08;如 28BYJ-48&#…

邮政编码,格式校验:@ZipCode(自定义注解)

目标 自定义一个用于校验邮政编码格式的注解ZipCode&#xff0c;能够和现有的 Validation 兼容&#xff0c;使用方式和其他校验注解保持一致&#xff08;使用 Valid 注解接口参数&#xff09;。 校验逻辑 有效格式 不能包含空格&#xff1b;应为6位数字&#xff1b; 不校验…

区块链在游戏行业的应用

区块链技术在游戏行业有许多潜在的应用&#xff0c;它可以改变游戏开发、发行和玩家交互的方式。以下是区块链技术在游戏行业的一些主要应用&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.游戏资产…

L05_SpringBoot入门

SpringBoot入门 浅谈Restful风格代码实现(并且通过Apifox进行接口测试[以传入json格式数据为例])首先创建一个SpringBoot项目,pom文件包引入如下下面在新建src创建com.ndky.controller包,然后再在包内创建一个HelloController类编写(一个简易的restful风格的代码)编写GET请求代…

智能工厂:APS高级计划排程系统成为了制造业建设智能工厂的核心必要需求

近年来&#xff0c;中国经济受到了许多因素的影响&#xff0c;例如新冠疫情冲击和国内外经济环境的巨大变化&#xff0c;随着我国人口红利的减少和人力成本逐步的增加&#xff0c;不论是中大型或小微制造企业为了提高市场竞争力并降低生产成本&#xff0c;都纷纷开始规划建设数…

C++QT-day6

/*定义一个基类 Animal&#xff0c;其中有一个虛函数perform&#xff08;)&#xff0c;用于在子类中实现不同动物的表演行为。*/ #include <iostream> using namespace std; class Animal //封装Animal类&#xff08;基类&#xff09; { private:string person; public:A…

Linux内存管理 (2):memblock 子系统的建立

前一篇&#xff1a;Linux内存管理 (1)&#xff1a;内核镜像映射临时页表的建立 文章目录 1. 前言2. 分析背景3. memblock 简介3.1 memblock 数据结构3.2 memblock 接口 4. memblock 的构建过程 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者…

Vue绑定样式

一、绑定class样式 语法格式&#xff1a; :class "属性名" &#xff08;一&#xff09;字符串写法 该写法适用于样式的类名不确定&#xff0c;需要动态指定的场景 我们用如下的CSS样式进行操作演示 我们要完成点击按钮改变CSS样式的操作&#xff0c;如下图代码所…

C# 中大小端Endian

大小端可以找下资料很多&#xff0c;都是文字的。我每次遇到大小端问题就会搜资料&#xff0c;总是记不住。我自己用用图片记录一下&#xff0c;以备直观的从内存中看到。 在C#中可以用BitConverter.IsLittleEndian来查询。 几个数字在内存中 我们来观察一下&#xff0c;我的…

js获取当前时间

// 格式化日对象 (获取当前时间) export function timeFormat() {var date new Date();var sign2 ":";var year date.getFullYear(); // 年var month date.getMonth() 1; // 月var day date.getDate(); // 日var hour date.getHours(); // 时var minutes dat…