unity 天空盒_Unity自定义可编程渲染管线(SRP)(二)——编写第一个自定义SRP

0cfc7abdfe00ac5e122bbb0779c2c1c9.png

一句话描述,我们可以把SRP分解成两个部分,分别是SRP Asset,SRP Instance。

SRP Asset

SRP Asset是一个Unity Asset文件,用来存储渲染管线的特定配置信息,包含的信息有:游戏物体是否应该投射阴影;使用什么样的着色器质量级别;影子距离;默认材质配置。

此外还可以保存所有像在配置中保存和控制的信息和unity需要序列化的数据。SRP Asset定义了SRP的类型和所有配置数据的设置。

SRP Instance

SRP Instance是实际执行渲染的类,当unity发现工程使用SRP的时候,就会寻找当前使用的SRP Asset并请求一个渲染实例,该实例必须包含一个Render函数,

渲染实例表示管道配置。在渲染调用中,Unity可以执行如下操作:

  • 清理framebuffer。
  • 执行场景清理。
  • 渲染游戏对象集。
  • 从一个帧缓冲区到另一个帧缓冲区执行位块传输;
  • 渲染阴影。
  • 应用后处理效果。

第一个SRP Asset案例

SRP Asset实际是一个继承RenderPipelineAsset接口的类,需要实现CreatePipeline接口。当unity首次执行渲染命令的时候,则会调用这个接口并返回一个可用的渲染实例。

下面所展示的就是一个简单的SRP Asset类。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;[CreateAssetMenu(menuName = "Rendering/Custom Render Pipeline")]
public class CustomRenderPipelineAsset : RenderPipelineAsset
{protected override RenderPipeline CreatePipeline(){return new CustomRenderPipeline();}
}

SRP Instance

在上面的叙述中,CustomRenderPipelineAsset类重写了CreatePipeline方法,并返回了一个CustomRenderPipeline实例对象,该对象则是unity SRP渲染的入口。CustomRenderPipeline是一个继承RenderPipeline的类,而且必须实现虚函数Render,该函数包含了两个参数:

ScriptableRenderContext context:是一个command buffer对象,可以向其输入您想执行的渲染指令。

Camera[] cameras:一系列用于渲染的相机。

先介绍一个简单的例子:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;public class CustomRenderPipeline : RenderPipeline
{public CameraRender cameraRender = new CameraRender();public CustomRenderPipeline(){}protected override void Render(ScriptableRenderContext context, Camera[] cameras){foreach(var camera in cameras){cameraRender.Render(context, camera);}}
}

如上所示,我们把渲染的处理逻辑封装到CameraRender类里,对每一个场景中的活动相机进行单独处理。

下一步先定义CameraRender类:

using UnityEngine;
using UnityEngine.Rendering;public class CameraRenderer {ScriptableRenderContext context;Camera camera;public void Render (ScriptableRenderContext context, Camera camera) {this.context = context;this.camera = camera;}
}

然后正式定义Render函数,实现我们的自定义渲染管线。

  1. 绘制天空盒

在Render函数中是要绘制所有Camera可见的几何体,我们声明一个函数DrawVisibleGeometry用于处理一些特殊的工作,绘制天空盒也是在这个方法中处理,不过我们还另外声明了一个方法来完成这个工作。代码如下:

public void Render (ScriptableRenderContext context, Camera camera) {this.context = context;this.camera = camera;DrawVisibleGeometry();}void DrawVisibleGeometry () {context.DrawSkybox(camera);}

然而这样仍不能显示天空盒,这是因为我们调用DrawSkybox只是把命令添加到context的缓存队列里,还需要调用context.Submit()方法才会正式执行缓存队列里面的命令。

public void Render (ScriptableRenderContext context, Camera camera) {this.context = context;this.camera = camera;DrawVisibleGeometry();Submit();}void Submit () {context.Submit();}

最后我们可以看到下面的效果。

6cd63f06b9b8c0ada6d54f3b78ccb333.png

但是,这个渲染结果还是有问题,当我们调整相机的角度或位置时,渲染结果并没有发生变化,这是因为我们并没有将视角投影矩阵传递给Command Buffer。这个变换矩阵在Unity Shader中是unity_MatrixVP。当我们打开frame debugger面板,选择一个draw call,这个变量就会显示在右侧的监视板上。当前,不管我们怎么调整相机的姿态,这个变量都会保持不变,通过调用SetupCameraProperties方法可以构建这个矩阵。如下所示

cb9dcd15a71acc6656d1155ff16b299a.png

但是,这个渲染结果还是有问题,当我们调整相机的角度或位置时,渲染结果并没有发生变化,这是因为我们并没有将视角投影矩阵传递给Command Buffer。这个变换矩阵在Unity Shader中是unity_MatrixVP。当我们打开frame debugger面板,选择一个draw call,这个变量就会显示在右侧的监视板上。当前,不管我们怎么调整相机的姿态,这个变量都会保持不变,通过调用SetupCameraProperties方法可以构建这个矩阵。如下所示

public void Render (ScriptableRenderContext context, Camera camera) {this.context = context;this.camera = camera;Setup();DrawVisibleGeometry();Submit();
}void Setup () {context.SetupCameraProperties(camera);
}

2. Command buffer

前面已经提到,context只有在调用Submit方法时才会执行渲染指令,在这之前都是将指令添加到渲染队列中。像天空盒可以通过专业的方法添加指令,但是像其他任务则不能通过这样添加,需要通过一个单独的command buffer间接添加。因此我们需要另建一个buffer用来绘制其他的几何对象。

const string bufferName = "Render Camera";CommandBuffer buffer = new CommandBuffer {name = bufferName
};

在项目开发中,profiler是一个非常强大和有用的工具,这里我们可以把我们的Command Buffer加入到profiler样例中,这个样例可以同时显示在profiler和frame debugger面板,方法是在适当的位置调用BeginSample和EndSample方法,在我们的案例中将会分别放在Setup()方法和Submit()方法的开头位置。BeginSample和EndSample方法必须使用相同的字符串参数作为样例的名字,这里使用的是buffer的名字。

void Setup () {buffer.BeginSample(bufferName);context.SetupCameraProperties(camera);
}void Submit () {buffer.EndSample(bufferName);context.Submit();
}

执行Command Buffer中的命令只需要调用context的ExecuteCommandBuffer方法,并把buffer作为参数传递进去。

void Setup () {buffer.BeginSample(bufferName);ExecuteBuffer();context.SetupCameraProperties(camera);
}void Submit () {buffer.EndSample(bufferName);ExecuteBuffer();context.Submit();
}void ExecuteBuffer () {context.ExecuteCommandBuffer(buffer);buffer.Clear();
}

这时候打开frame debugger我们就可以看到渲染的案例如下:

8c108b9326c96f13fcd32d1f7002d011.png

3. 清除渲染目标

不管我们想要绘制什么东西,最终都会渲染到相机的渲染目标中。相机的渲染目标一般是帧缓存区,也可以是渲染纹理。渲染目标一般不会自动清除,也就是说之前渲染的结果会一直保存在渲染目标中,这样会干扰我们渲染新的图像。为了保证正确的渲染,我们必须清除渲染目标,以摆脱其旧的内容。通过调用ClearRenderTarget方法可以实现这个目的。

ClearRenderTarget函数需要至少三个参数,前两个参数指定是否清理颜色缓存和深度缓存,一般都设为true,第三个参数指定清理缓存的颜色,这里使用Color.clear。

void Setup () {buffer.BeginSample(bufferName);buffer.ClearRenderTarget(true, true, Color.clear);ExecuteBuffer();context.SetupCameraProperties(camera);
}

4d4386483eb9207885c5cb813dd2804a.png

打开frame debugger,可以看到清理渲染目标活动对应了一个叫DrawGL的样例。而且这个案例被镶嵌在另一个Render Camera样例中,这是因为 ClearRenderTarget将清除任务包装在了一个使用Command buffer的名字命名的样例中。为了避免这种情况,可以调整一下清除目标的代码的位置。

void Setup () {context.SetupCameraProperties(camera);buffer.ClearRenderTarget(true, true, Color.clear);buffer.BeginSample(bufferName);ExecuteBuffer();//context.SetupCameraProperties(camera);
}

016d751bd45377e6cffc890a04e580f3.png

现在我们可以看到Clear(color+Z+stencil),这表明颜色跟深度缓冲都没清除了,stencil数据是同一缓存区的一部分。

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

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

相关文章

【design pattern】工厂方法模式和抽象工厂模式

前言 设计模式分为三大类: 创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式; 结构型模式:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式; 行为型模式&#xff1…

弹簧触摸开关原理图_10年老电工经验之谈:常见的开关电源那些事儿

随着电控系统中对控制回路安全性要求提高,控制回路的工作电压是越来越趋于直流低压化。由此,控制回路内各种使用直流电源的传感器、中小微型直流继电器等电器装置是日益增多。也正因如此,电控系统内不同品牌的开关电源也相应地多了起来。因牵…

erlang mysql连接超时_Erlang数据库-(一)Erlang与Mysql的连接

下载:http://download.csdn.net/detail/hjhjava/7088277把该文件的东西全部编译好,然后根据下面的解释就可以操作Mysql的。很简单~-record(row,{a1 0, a20}).%% 第一个参数是该链接的名字(根据它来操作Mysql),第二参数是本机号(ip地址)%% &a…

管理活动目录域服务实训_管理学院学生党支部开展实践教育基地服务活动

红星E校有态度 有温度 可关注为进一步加强党的建设,深化管理学院学生党支部与实践基地的互动性,2020年9月11至12日,管理学院学生党支部协助白鹤村村委实践基地完成第七次人口普查相关工作,共计6名预备党员参与。工作开始前的培训会…

mysql 汉编码 的选_peewee连接mysql汉语言数据编码_mysql

peewee连接mysql中文数据编码系统是win7 x64python 2.7.6的site.py里面编码设定为 utf-8py文件首行指定 #coding:utf-8mysql 5.5.38安装时指定代码为utf-8peewee的连接数据库代码为:db MySQLDatabase(host 127.0.0.1, user root, passwd 1, database mz, chars…

配置windows失败,还原更新,请勿关机

最近给同事装系统,偶尔会出现如下问题: 如果是这种情况,只能耐心等待了,因为关机也没用! 转载于:https://www.cnblogs.com/lijy/p/5327844.html

使用uicollectionView时需要注意的问题

1.UICollectionView使用流水布局——UICollectionViewFlowLayout时,需要满足条件: 每个item(即cell)的大小是一样的,不仅是宽度,还有高度。这样,当collectionview的宽度发生变化时,item能将其动态填充。ite…

swift 从手机选照片_19元起!定制专属手机壳!还可免费打印照片...

△剧透:文末有福利现在的年轻人体内涌动的都是追求有趣有特色的灵魂希望自己是这条gai最独一无二的仔撞衫撞包撞手机壳可以说是当代年轻人三大时尚忌讳尤其是手机壳极为重要毕竟换壳≈换机只需要几十元买新壳就可以拥有换新机般的仪式感不过作为手机壳老手都知道在某…

新手也能学会本地调试微信,natapp 官网映射

本地调试微信的新手指引~ 照着配置,一定可以配置成功,实现本地调试微信,公司好几个同事按照我写的步骤,都独立配成功了。 1.首选在natapp注册一个账号,申请免费隧道或者购买隧道,我买了一个月9元的付费隧道…

c实现三角形角度大于一个值_初中数学三角形知识点小结

▊ 三角形两边定理:三角形两边的和大于第三边。推论:三角形两边的差小于第三边。▊ 三角形中位线定理三角形的中位线平行于第三边,并且等于它的一半。▊ 三角形的重心三角形的重心到顶点的距离是它到对边中点距离的2倍。在三角形中&#x…

【Spring】使用Spring和AMQP发送接收消息(下)

为什么80%的码农都做不了架构师?>>> 上篇讲了RabbitMQ连接工厂的作用是用来创建RabbitMQ的连接,本篇就来讲讲RabbitMQ的发送消息。通过RabbitMQ发送消息最简单的方式就是将connectionFactory Bean注入到服务层类中,并使用它创建C…

微软u盘安装工具_使用微软Winget工具安装软件教程

对于系统管理员来说,一款好用的软件包管理工具可以大大提高安装、部署、管理软件的效率。可之前只有 MscOS 和 Linux 官方才有软件包管理工具,微软官方现在终于为Windows系统发布了一款名为Winget的软件包管理工具,MS酋长下面就来为大家演示一…

RandomForestClassifier(随机森林检测每个特征的重要性及每个样例属于哪个类的概率)...

#In the next recipe, well look at how to tune the random forest classifier. #Lets start by importing datasets:from sklearn import datasets X, y datasets.make_classification(1000)# X(1000,20) #y(1000) 取值范围【0,1】from sklearn.ensemble import RandomFores…

单因素方差分析_基于R语言开展方差分析(一)——单因素方差分析

基本原理方差分析(Analysis of variance, ANOVA)是用于两个或两个以上样本均数比较的方法,还可以分析两个或多个研究因素的交互交互作用以及回归方程的线性假设检验等。其基本思想是将全部观察值间的变异——总变异按设计和需要分解成两个或多个组成部分&#xff0c…

mysql增数据语句_Mysql 数据增删改查语句

插入数据 insert#1. 插入完整数据(顺序插入)#语法一:insert into 表名(字段1,字段2,字段3…字段n) values (值1,值2,值3…值n);#语法二:insert into 表名 values (值1,值2,值3…值n);#2. 指定字段插入数据#语法:insert into 表名(字段1,字段2…

Python+Flask.0010.FLASK即插视图之自定义视图类及修饰器

2019独角兽企业重金招聘Python工程师标准>>> 即插视图; 说明: FLASK的视图灵感来自于DJANGO的基于类而非基于函数的通用视图,主要目的是为了解决多个视图函数之间已经实现的部分,通过类继承的方式继承到其它视图,总之为了一点,就是少写代码,然后通过add_url_rule让我…

InputStream和Reader,FileInputStream和 FileReader的区别

一、InputStream和Reader的区别 InputStream和Reader都可以用来读数据(从文件中读取数据或从Socket中读取数据),最主要的区别如下: InputStream用来读取二进制数(字节流),而 Reader用来读取文本数据,即 Unicode字符。那么二进制数与文本数据有…

NGUI之输入文本框的使用

ToolBar中的两个红圈 另,代码如下:只需要定义一个变量即可,然后将控件drag到那里,真的是灰常方便呀 还有一个就是保存了(OK的响应),可以简单地理解为存档或读档 转载于:https://www.cnblogs.com/YTYMblog/p…

tensorrt轻松部署高性能dnn推理_实战教程:TensorRT中递归神经网络的介绍(中文字幕)...

NVIDIA TensorRT是一个高性能的深度学习推理优化器和运行时,它提供低延迟和高吞吐量。TensorRT可以从每个深度学习框架导入经过训练的模型,从而轻松地创建可以集成到大型应用程序和服务中的高效推理引擎。这个视频的五个关键点:1.TensorRT支持RNNv2, Mat…

w怎么接显示 树莓派zero_纯干货!一根线玩转树莓派ZeroW(图文教程,亲测有效)...

#一、写在前面本文旨在介绍如何用最少的外设(成本)完成树莓派Zero W最基础最重要的功能。注意:本文原始发表时官方镜像版本是2017-04-10的,在2019年5月10日有网友提出本方案已经不完全适用最新的镜像了,所以如果只是想按照本文所提出的步骤一…