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.pswp.cn/news/396488.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396488.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396488.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

構建node.js基礎鏡像_在Android上構建Node.js應用程序

構建node.js基礎鏡像by Aurlien Giraud通過AurlienGiraud 在Android上構建Node.js應用程序 (Building a Node.js application on Android) 第2部分:Express和NeDB (Part 2: Express and NeDB) In Part 1 we saw how to use Termux, a Terminal emulator and Linux …

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

前言 設計模式分為三大類: 創建型模式:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式; 結構型模式:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式; 行為型模式&#xff1…

linux中使用隨機數

(1)單純使用rand重復調用n次,就會得到一個0-RAND_MAX之間的偽隨機數,如果需要調整范圍,可以得到隨機數序列后再進行計算。(2)單純使用rand來得到偽隨機數序列有缺陷,每次執行程序得到的偽隨機序列是同一個序列,沒法得到…

mysql 異地備份工具_異地備份簡單實現(mysql)

該腳本只適用于MYISAM引擎,如果需要適用于innodb,請修改備份命令即可。#!/bin/bash#該腳本只能用來備份myisam引擎數據庫#author:vaedit#date:2017/9/18#備份過程function beifen(){BACKDIRdate "%Y-%m-%d-%H"mkdir /backup/$BACKD…

python管理數據庫設計_Pycharm+Django+Python+MySQL開發 后臺管理數據庫

Django框架十分簡單易用,適合搭建個人博客網站。網上有很多教程,大多是關于命令行操作Django,這里分享一些用最新工具進行Django開發過程,主要是PyCharm太強大,不用有點可惜。第一次寫技術開發類的博文,可能…

你鼓舞了我是世界杯主題曲嗎_選擇方法和鼓舞人心的網站列表

你鼓舞了我是世界杯主題曲嗎by Kristoffer Andreasen通過克里斯托弗安德烈森 選擇方法和鼓舞人心的網站列表 (The pick and choose approach and a list of inspirational websites) In the past couple of years I have created quite a few websites. In the beginning, I h…

共享程序集GAC

原文標題: 原文地址:https://www.cnblogs.com/1996V/p/9037603.html 共享程序集GAC 我上面說了這么多有關CLR加載程序集的細節和規則,事實上,類似于mscorlib.dll、System.dll這樣的FCL類庫被引用的如此頻繁,它已經是我…

彈簧觸摸開關原理圖_10年老電工經驗之談:常見的開關電源那些事兒

隨著電控系統中對控制回路安全性要求提高,控制回路的工作電壓是越來越趨于直流低壓化。由此,控制回路內各種使用直流電源的傳感器、中小微型直流繼電器等電器裝置是日益增多。也正因如此,電控系統內不同品牌的開關電源也相應地多了起來。因牽…

erlang mysql連接超時_Erlang數據庫-(一)Erlang與Mysql的連接

下載:http://download.csdn.net/detail/hjhjava/7088277把該文件的東西全部編譯好,然后根據下面的解釋就可以操作Mysql的。很簡單~-record(row,{a1 0, a20}).%% 第一個參數是該鏈接的名字(根據它來操作Mysql),第二參數是本機號(ip地址)%% &a…

SQL SERVER 中 GO 的用法2

具體不廢話了&#xff0c;請看下文詳解。 12345678910use db_CSharpgoselect *,備注casewhen Grade>90 then 成績優秀when Grade<90 and Grade>80 then 成績良好when Grade<80 and Grade>70 then 成績及格else 不及格endfrom tb_Grade如果只是執行一條語句&…

js中判斷值不等于undefined

文章&#xff1a;JS 中判斷空值 undefined 和 null轉載于:https://www.cnblogs.com/Tpf386/p/9804496.html

reddit_我在3天內瘋狂地審查了Reddit上的50個投資組合,從中學到了什么。

redditI’ve always enjoyed critiquing applicants’ portfolios at the design studio where I work. And I also often ask for feedback on my own designs on Reddit’s webdev subreddit.我一直都很喜歡在我工作的設計工作室里評估申請人的作品集。 我也經常在Reddit的we…

【BZOJ1001】[BeiJing2006]狼抓兔子

挺簡單一個題&#xff0c;最小割模板 我的感覺就是可能建圖的時候會比較麻煩吧&#xff0c;畢竟三個方向。 #include <cctype> #include <climits> #include <cstdio> #include <cstring> #include <iostream>#define debug(x) std::cout <&l…

管理活動目錄域服務實訓_管理學院學生黨支部開展實踐教育基地服務活動

紅星E校有態度 有溫度 可關注為進一步加強黨的建設&#xff0c;深化管理學院學生黨支部與實踐基地的互動性&#xff0c;2020年9月11至12日&#xff0c;管理學院學生黨支部協助白鶴村村委實踐基地完成第七次人口普查相關工作&#xff0c;共計6名預備黨員參與。工作開始前的培訓會…

mysql 漢編碼 的選_peewee連接mysql漢語言數據編碼_mysql

peewee連接mysql中文數據編碼系統是win7 x64python 2.7.6的site.py里面編碼設定為 utf-8py文件首行指定 #coding:utf-8mysql 5.5.38安裝時指定代碼為utf-8peewee的連接數據庫代碼為&#xff1a;db MySQLDatabase(host 127.0.0.1, user root, passwd 1, database mz, chars…

配置windows失敗,還原更新,請勿關機

最近給同事裝系統&#xff0c;偶爾會出現如下問題&#xff1a; 如果是這種情況&#xff0c;只能耐心等待了&#xff0c;因為關機也沒用&#xff01; 轉載于:https://www.cnblogs.com/lijy/p/5327844.html

使用Express和MongoDB構建簡單的CRUD應用程序

by Zell Liew由Zell Liew 使用Express和MongoDB構建簡單的CRUD應用程序 (Building a Simple CRUD Application with Express and MongoDB) For a long time, I didn’t dare venture into back end development. I felt intimidated because of my lack of an academic backgr…

python元類的使用_python中元類用法實例

本文實例講述了python中元類用法&#xff0c;分享給大家供大家參考。具體方法分析如下&#xff1a;1.元類(metaclass)是用來創建類的類2.type(object):返回一個對象的類型&#xff0c;與object.__class__的值相同&#xff0c;type(name,bases,dict):創建一個新的type類型&#…

使用uicollectionView時需要注意的問題

1.UICollectionView使用流水布局——UICollectionViewFlowLayout時&#xff0c;需要滿足條件&#xff1a; 每個item(即cell)的大小是一樣的&#xff0c;不僅是寬度&#xff0c;還有高度。這樣&#xff0c;當collectionview的寬度發生變化時&#xff0c;item能將其動態填充。ite…

hiveql函數筆記(二)

1、數據查詢 //提高聚合的性能 SET hive.map.aggrtrue; SELECT count(*),avg(salary) FROM employees; //木匾不允許在一個查詢語句中使用多于一個的函數&#xff08;DISTINCT。。。&#xff09;表達式 SELECT count(DISTINCT symbol) FROM stocks; 表生成函數&#xff1a; exp…