快手動(dòng)效渲染引擎Crab,解鎖“游戲化動(dòng)效”開發(fā)新方式! 原創(chuàng)
導(dǎo)讀:在上一篇文章中,我們?nèi)轿坏亟馕隽丝焓諺ision動(dòng)效平臺(tái)的整體架構(gòu)及其演進(jìn)思路??焓智岸藙?dòng)效大揭秘:告別低效,vision平臺(tái)來襲!?????今天,我們將進(jìn)一步深入,詳細(xì)介紹Vision動(dòng)效平臺(tái)的渲染引擎——Crab,并分享在復(fù)雜動(dòng)效渲染場(chǎng)景下積累的實(shí)踐經(jīng)驗(yàn)和精彩案例。
?
一、項(xiàng)目背景
?
1.1 快手大型活動(dòng)中的動(dòng)效
動(dòng)效在設(shè)計(jì)和用戶體驗(yàn)領(lǐng)域中有重要的價(jià)值,表現(xiàn)力強(qiáng)的動(dòng)效不僅能夠激發(fā)受眾用戶的興趣,提高參與度,還能提高留存和用戶活躍度,最終增強(qiáng)用戶對(duì)產(chǎn)品的粘性,因此活動(dòng)中的動(dòng)效越來越復(fù)雜。
下圖是我們開發(fā)過的具有復(fù)雜動(dòng)效的活動(dòng)案例。
可以看到,在這些活動(dòng)中,最顯眼的KV部分由持續(xù)播放的動(dòng)效進(jìn)行承接,并且動(dòng)效需要在用戶游玩活動(dòng)的過程中進(jìn)行反饋。另外,因?yàn)檫@些動(dòng)效的持續(xù)時(shí)間非常長,且位置顯眼,所以為了保證用戶的體驗(yàn),需要這些動(dòng)效在盡可能多的設(shè)備上正常展示。
總的來說,這類動(dòng)效有三個(gè)特點(diǎn):高表現(xiàn)力,高可交互性和高兼容度,為了方便說明,我們將同時(shí)滿足這三個(gè)特點(diǎn)的動(dòng)效稱為「游戲化動(dòng)效」。?
1.2 “常規(guī)”動(dòng)效的實(shí)現(xiàn)方案和局限
一般情況下,動(dòng)效的實(shí)現(xiàn)可以分成兩種類型的方案:關(guān)鍵幀方案以及逐幀方案。
常規(guī)的關(guān)鍵幀方案有CSS和Lottie,比較簡單的動(dòng)效選用CSS更好,比較復(fù)雜的動(dòng)效選擇Lottie可以更好的保證開發(fā)效率和動(dòng)效還原。CSS和Lottie的優(yōu)勢(shì)是通用和常規(guī),但缺點(diǎn)是只能適合實(shí)現(xiàn)基礎(chǔ)Transform或矢量圖形變化的平面動(dòng)效。
常規(guī)的逐幀方案有序列幀,以及APNG,視頻和透明視頻這些針對(duì)不同場(chǎng)景的改進(jìn)版本的類序列幀方案。逐幀方案的動(dòng)效單幀表現(xiàn)力上限非常高,但代價(jià)是幾乎沒有可交互能力,基本只能制作單純的播片邏輯動(dòng)效。
總的來說,“常規(guī)”的動(dòng)效實(shí)現(xiàn)方案只能滿足可交互性和表現(xiàn)力的其中一種,很難兼顧,無法滿足業(yè)務(wù)中游戲化動(dòng)效的需求。
1.3 如何實(shí)現(xiàn)兼顧表現(xiàn)力和可交互性?
要實(shí)現(xiàn)兼顧可交互性和表現(xiàn)力的動(dòng)效,就需要相比常規(guī)動(dòng)效實(shí)現(xiàn)手段對(duì)動(dòng)畫元素控制性更強(qiáng)的實(shí)現(xiàn)手段。對(duì)于這個(gè)需求,最適配的方案就是使用WebGL。
WebGL是一個(gè)給基于OpenGL ES的低級(jí)3D圖形API使用的開放Web標(biāo)準(zhǔn)。通過WebGL的能力,我們對(duì)動(dòng)畫元素的控制粒度可以精細(xì)到該動(dòng)畫元素的細(xì)分圖元層面,對(duì)動(dòng)畫元素渲染表現(xiàn)控制可以精細(xì)到單個(gè)像素層面。有了這種控制精度,就有了同時(shí)兼顧可交互性和表現(xiàn)力的底層支持。
為什么是Crab?
WebGL的API是低級(jí)3D圖形API,在實(shí)際業(yè)務(wù)使用中很難直接使用這個(gè)API,下面是使用WebGL直接繪制一張三角形的示例:
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}
function createProgram(
gl,
vertexShader,
fragmentShader
) {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
return program;
}
let fragStr = `#version 300 es
precision mediump float;
in vec2 position;
out vec4 outColor;
void main () {
outColor = vec4(1., 0., 0., 1.);
}
`;
let vertStr = `#version 300 es
in vec2 a_position;
uniform vec2 u_resolution;
out vec2 position;
void main() {
position = a_position;
gl_Position = vec4(a_position * 2. - 1., 0. ,1.);
}
`;
let positions = new Float32Array([.5, 1., 1., 0., 0., 0.]);
let canvas = document.querySelector('#can');
let video = document.querySelector('video');
canvas.width = 640;
canvas.height = 320;
let gl = canvas.getContext('webgl2');
let program = createProgram(
gl,
createShader(gl, gl.VERTEX_SHADER, vertStr),
createShader(gl, gl.FRAGMENT_SHADER, fragStr)
);
gl.useProgram(program);
gl.viewport(0, 0, canvas.width, canvas.height);
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
const positionbuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionbuffer);
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
gl.enableVertexAttribArray(positionAttributeLocation);
const size = 2;
const type = gl.FLOAT;
const normalize =false;
const stride = 0;
const offset = 0;
gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset);
gl.bindVertexArray(vao);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
const primitiveType = gl.TRIANGLES;
const doffset = 0;
const count = 3;
gl.drawArrays(primitiveType, doffset, count);
近百行的代碼量才能渲染出如下的一個(gè)簡單的三角形:
因此我們應(yīng)通過封裝完成的引擎來使用WebGL能力。
在進(jìn)行動(dòng)效渲染引擎的挑選之前,我們首先明確了四點(diǎn)挑選原則:
- 實(shí)現(xiàn)輕量化:實(shí)現(xiàn)動(dòng)效時(shí),只引入所需的引擎內(nèi)容,控制依賴包的體積
- 可擴(kuò)展性:可以方便的進(jìn)行動(dòng)效的渲染特性和交互特性的開發(fā),而無需任何細(xì)節(jié)都強(qiáng)依賴于引擎的具體能力支持
- 便于沉淀:渲染特性和交互特性的擴(kuò)展有相對(duì)標(biāo)準(zhǔn)的接口和使用規(guī)范,方便進(jìn)行沉淀和日后其他場(chǎng)景的復(fù)用。
- 游戲化動(dòng)效和業(yè)務(wù)在同一倉庫下維護(hù):減少協(xié)作成本,便于開發(fā)、調(diào)試和維護(hù)。
?
基于這四點(diǎn)原則,我們調(diào)研了已有的可選方案,發(fā)現(xiàn)它們都不能完全滿足我們的需求,因此我們選擇了自研Crab動(dòng)效渲染引擎。
?
二、Crab簡介
Crab是一款可在支持WebGL的環(huán)境(Web,快手小游戲等)中使用的游戲化動(dòng)效渲染引擎。
2.1 流程Crab的分層架構(gòu)方式
Crab大體可以分為接入層、資產(chǎn)抽象層、擴(kuò)展層、運(yùn)行層和功能層,其中接入層、資產(chǎn)抽象層、擴(kuò)展層、運(yùn)行層都位于引擎的核心包中,功能層則由業(yè)務(wù)使用中積累的一些具有通用性功能的第一方或第三方的獨(dú)立包組成。
這種分層架構(gòu)方式有什么好處?
我們的游戲化動(dòng)效引擎實(shí)現(xiàn)的指導(dǎo)原則就是上面提到過的實(shí)現(xiàn)輕量化、可擴(kuò)展性、便于沉淀以及方便維護(hù),這種架構(gòu)方式可以很好滿足我們的要求:
- 可擴(kuò)展性: 擴(kuò)展層的RenderProcessor和RenderPipeline
?提供了渲染上的擴(kuò)展能力, Component和System提供了邏輯上的擴(kuò)展能力, 通過它們,我們保證了這個(gè)引擎的擴(kuò)展能力 - 便于沉淀: 使用擴(kuò)展層擴(kuò)展出來的功能如果有沉淀價(jià)值, 可以單獨(dú)發(fā)包, 作為功能層的一員
- 實(shí)現(xiàn)輕量化: 正如剛才提到的, 大部分具體功能都位于功能層的不同包內(nèi), 所以我們的核心包比較輕量, 在使用功能的時(shí)候也可以只引入對(duì)應(yīng)功能的包.
- 游戲化動(dòng)效和業(yè)務(wù)在同一倉庫下維護(hù): 作為一個(gè)主要使用TS和WebGL API的前端庫,Crab可以自然的在前端項(xiàng)目中使用。
2.2 Crab一個(gè)Tick的處理流程
接下來我們從Crab的一個(gè)Tick入手,介紹下擴(kuò)展層的實(shí)現(xiàn)方式。
Crab在一個(gè)Tick的不同時(shí)機(jī),放置了許多可以執(zhí)行邏輯鉤子的階段,以此作為暴露交互能力的接口。使用者可以注冊(cè)自己的鉤子來執(zhí)行自定義的邏輯操作。
在這些邏輯鉤子中間的渲染處理部分(Render Processor)則用來執(zhí)行渲染操作,同樣提供暴露渲染能力的接口。
2.2.1 邏輯處理部分
Crab中渲染的場(chǎng)景是通過一個(gè)由許多節(jié)點(diǎn)組成的樹狀結(jié)構(gòu)來描述的,節(jié)點(diǎn)上可以掛載不同的組件,組件中可以包含關(guān)于該節(jié)點(diǎn)的不同描述信息,比如Transform節(jié)點(diǎn)用于描述一個(gè)節(jié)點(diǎn)的位置信息,Renderable節(jié)點(diǎn)用于描述一個(gè)可渲染節(jié)點(diǎn)的渲染信息。
節(jié)點(diǎn)組件中的信息可以被用戶注冊(cè)的邏輯鉤子讀寫,用戶可以通過實(shí)現(xiàn)和注冊(cè)System的方式來進(jìn)行邏輯鉤子的實(shí)現(xiàn)和注冊(cè)。不同的System可以指定只對(duì)滿足某些特定條件的節(jié)點(diǎn)生效(比如必須掛載某個(gè)組件/必須沒有掛載某個(gè)組件)以及要注冊(cè)哪些階段的邏輯鉤子。
通過這種方式,使用者可以將不同的描述信息放入不同的組件中,將不同的操作邏輯放入不同的System中,有相關(guān)性的組件和System可以自然的組合作為一個(gè)功能的實(shí)現(xiàn),可以增強(qiáng)代碼的可讀性并簡化進(jìn)行功能沉淀所需的前置操作。
2.2.2 渲染處理部分
渲染處理部分(Render Processor)主要由1個(gè)或多個(gè)渲染階段(Render Stage)連接組成,每個(gè)渲染階段的渲染結(jié)果可以作為該幀畫面的最終展示效果,或者作為渲染出一幀畫面需要的中間結(jié)果。每個(gè)渲染階段可以執(zhí)行場(chǎng)景中匹配的可渲染節(jié)點(diǎn)中的渲染管線(Render Pipeline),渲染管線是Crab中渲染的最小單元,會(huì)執(zhí)行一次Draw Call,以及該Draw Call相關(guān)的數(shù)據(jù)綁定,標(biāo)志設(shè)置等邏輯。
使用不同的渲染階段和連接方式,以及不同的渲染管線設(shè)置,就可以滿足不同的渲染需求。
渲染階段
渲染階段是組成Crab的渲染處理部分的基礎(chǔ)模塊,Crab提供了四種類型的渲染階段,來滿足從FrameBuffer/場(chǎng)景到FrameBuffer/屏幕的不同連接需求。
四種渲染階段都可選接收用戶傳入的渲染信息,比如Shader,Viewport,是否刷新FrameBuffer等。Crab中的渲染階段具有自由度很高的可擴(kuò)展性,且可以像樂高積木一樣互相拼接,用戶可以利用它自由實(shí)現(xiàn)陰影,延遲渲染,后處理效果等渲染特性,也可以組合各種不同的渲染特性,積累自定義渲染流程,具有通用性的自定義渲染流程也可以通過發(fā)布為Crab功能層的一部分,獲得更多的使用。
渲染管線
渲染管線是執(zhí)行渲染的最小單元。內(nèi)部維護(hù)了引用的Shader信息,以及對(duì)應(yīng)的Shader變量,數(shù)據(jù)和宏開關(guān)等與一次Draw Call相關(guān)的信息。當(dāng)要執(zhí)行一個(gè)渲染管線的渲染時(shí),Crab會(huì)根據(jù)其包含的數(shù)據(jù)和宏等生成實(shí)例ID,以此判斷渲染執(zhí)行時(shí)是否需要?jiǎng)?chuàng)建新的實(shí)例,減少實(shí)例創(chuàng)建和切換成本。
渲染管線一般被裝載在可渲染(Renderable)組件中,Crab的內(nèi)置渲染System會(huì)自動(dòng)執(zhí)行匹配節(jié)點(diǎn)的可渲染組件中的渲染管線進(jìn)行渲染,使用者可以直接使用Crab已經(jīng)封裝的可渲染組件,比如通用Unlit
?渲染組件、通用Blinn-Phong渲染組件、粒子渲染組件、Spine渲染組件等來拼裝需要的效果。使用者也可以擴(kuò)展自己的可渲染組件,通過傳入Shader、混合模式等信息來實(shí)現(xiàn)自定義的渲染效果。
三、游戲化動(dòng)效的應(yīng)用與實(shí)踐
在業(yè)務(wù)中使用Crab支持游戲化動(dòng)效的過程中,我們也積累了一些通用的方案和功能,比如粒子系統(tǒng),Spine支持、一些材質(zhì)和后處理效果等。
3.1 2D動(dòng)效方案應(yīng)用
Spine
Spine是一種基于2D的骨骼動(dòng)畫實(shí)現(xiàn)方案,相比于常規(guī)動(dòng)效,它超越了傳統(tǒng)2D動(dòng)畫的限制,能帶來2.5D的體驗(yàn)。相比于3D動(dòng)效,它的制作和渲染更加輕量,是一種比較平衡的動(dòng)畫方案。
?,時(shí)長00:07
Crab對(duì)使用Spine動(dòng)畫時(shí)常用的動(dòng)畫播放、皮膚疊加/替換以及掛點(diǎn)功能進(jìn)行了封裝和支持,同時(shí)還提供了Spine資產(chǎn)的加載器,使用者在使用過程中可以不關(guān)注Spine的實(shí)現(xiàn)細(xì)節(jié),從而更好的聚焦在業(yè)務(wù)邏輯等其他部分的實(shí)現(xiàn)上。
置換貼圖
置換貼圖是AE提供的一項(xiàng)能力,它能實(shí)現(xiàn)類似于Spine的2D骨骼動(dòng)畫的簡易的效果,且素材生產(chǎn)成本相比Spine更低,因此在2D的氛圍動(dòng)效等相對(duì)重要性不高的動(dòng)效實(shí)現(xiàn)時(shí)是一種具有性價(jià)比的實(shí)現(xiàn)方案。
置換貼圖的實(shí)現(xiàn)原理:
要實(shí)現(xiàn)置換貼圖的效果,需要三個(gè)素材,分別是:
- 一張顏色貼圖,用于表明渲染的像素色值
- 一張位移系數(shù)貼圖,用來表明每個(gè)像素進(jìn)行形變的相對(duì)強(qiáng)度
- 一組包含全局位移方向和強(qiáng)度的動(dòng)畫片段
設(shè)計(jì)師在AE中對(duì)一個(gè)圖層的全局位移方向和強(qiáng)度進(jìn)行動(dòng)畫關(guān)鍵幀的設(shè)置,就可以得到一個(gè)非線形形變的動(dòng)畫效果。簡單說明的話,置換貼圖效果可以被看作只由一根骨骼控制的,在一個(gè)貼圖分辨率大小的平面網(wǎng)格上的骨骼動(dòng)畫。
3.2 3D動(dòng)效方案應(yīng)用
模型材質(zhì)
上限最高的渲染方式自然是基于物理的渲染方式,但是這種渲染方式有一個(gè)問題在于,在簡單的光照條件且不引入光線追蹤時(shí),渲染效果一般比較粗糙,而如果設(shè)置復(fù)雜的光照條件和材質(zhì)參數(shù),則渲染參數(shù)的調(diào)試成本和性能消耗都會(huì)很大。
對(duì)于這種性能和渲染效果上的困境,我們?cè)趯?shí)踐中選擇了另一種材質(zhì)——Matcap材質(zhì)。Matcap材質(zhì)的本質(zhì)是通過預(yù)計(jì)算貼圖保留了一個(gè)材質(zhì)在各個(gè)可見方向上的顏色信息,可以很好的保留C4D等軟件中的渲染效果;引擎實(shí)時(shí)渲染時(shí),只需要讀取貼圖,當(dāng)場(chǎng)景中不存在動(dòng)態(tài)光源時(shí),可以在較低的性能消耗下,實(shí)現(xiàn)接近離線渲染的表現(xiàn)效果。
Matcap材質(zhì)的實(shí)現(xiàn)原理
要實(shí)現(xiàn)這個(gè)材質(zhì),需要三種貼圖:索引貼圖,Matcap貼圖以及可選的顏色貼圖。
當(dāng)進(jìn)行著色時(shí),首先訪問索引貼圖,獲得該像素點(diǎn)對(duì)應(yīng)的Matcap貼圖索引,然后依據(jù)該點(diǎn)上的法線向量,從對(duì)應(yīng)的Matcap貼圖獲取特定位置的像素作為最終使用的像素即可。
對(duì)于顏色比較少的材質(zhì),直接使用Matcap貼圖上的顏色信息沒什么問題,但如果顏色比較多,需要的Matcap貼圖的數(shù)量將會(huì)是難以接受的,為了避免Matcap貼圖數(shù)量的暴漲,可以使用一張顏色貼圖,最終顏色不再直接使用Matcap貼圖中存儲(chǔ)的顏色,而是通過Mapcap貼圖中的顏色和顏色貼圖中的顏色混合得到。
模型動(dòng)作
動(dòng)作過渡
要實(shí)現(xiàn)一個(gè)生動(dòng)的3D角色,需要保證它持續(xù)活動(dòng)著,最簡單的方法就是時(shí)刻保持在模型上至少應(yīng)用一個(gè)動(dòng)畫片段。
不同的動(dòng)畫片段之間切換的時(shí)候,如果不做任何優(yōu)化,效果會(huì)很生硬,對(duì)此我們應(yīng)用了動(dòng)畫過渡和混合的能力,可以在不增加設(shè)計(jì)師工作量的前提下,提高動(dòng)畫的流暢度。
未應(yīng)用動(dòng)作過渡 | 應(yīng)用動(dòng)作過渡 |
頂點(diǎn)形變動(dòng)畫
骨骼動(dòng)畫是基于關(guān)節(jié)Transform混合的動(dòng)畫,雖然在大部分情況下的表現(xiàn)都足夠優(yōu)秀,但是在諸如表情動(dòng)畫等對(duì)形變的精細(xì)性要求更高的場(chǎng)景下往往顯得不夠生動(dòng)。
對(duì)此我們應(yīng)用了頂點(diǎn)形變動(dòng)畫的方案,頂點(diǎn)形變動(dòng)畫的原理是保存網(wǎng)格的多份快照,并在動(dòng)畫過程中改變不同快照的應(yīng)用權(quán)重,從而實(shí)現(xiàn)精細(xì)動(dòng)畫的效果。
表情快照 | 動(dòng)畫效果 |
多快照的兼容性實(shí)現(xiàn)
頂點(diǎn)快照信息一般使用貼圖的方式在Shader中進(jìn)行使用,最理想的實(shí)現(xiàn)方式是使用Texture Array的方式存儲(chǔ)頂點(diǎn)快照,但Texture Array是在WebGL2上才全面支持的特性,對(duì)只能使用WebGL1的設(shè)備,如果用普通的2D貼圖存儲(chǔ)頂點(diǎn)快照,則受限于貼圖數(shù)量的限制,以及材質(zhì)的其他特性所需貼圖(顏色貼圖,法線貼圖,AO貼圖等)擠占位置,會(huì)導(dǎo)致可以應(yīng)用的快照數(shù)量非常有限,為了讓只能使用WebGL1的設(shè)備也可以實(shí)現(xiàn)多快照的頂點(diǎn)形變動(dòng)畫,我們?cè)谶@種情況下將所有快照存放在同一個(gè)2D貼圖中,并實(shí)現(xiàn)專門的查找函數(shù)查找對(duì)應(yīng)的頂點(diǎn)快照信息,在WebGL1的上下文中實(shí)現(xiàn)了兼容更多快照的頂點(diǎn)形變動(dòng)畫。
3.3 特效應(yīng)用
粒子系統(tǒng)
粒子系統(tǒng)是非常常見的特效方案,可以用于模擬火、煙、云、水、落葉等自然現(xiàn)象,也可以用來模擬發(fā)光軌跡、速度線等抽象視覺效果。
6
Crab中提供了一套粒子系統(tǒng)以供使用。
Crab的粒子系統(tǒng)
Crab的粒子系統(tǒng)實(shí)現(xiàn)參考了Unity的粒子系統(tǒng)組織方式,由多個(gè)組件構(gòu)成,這些組件可以氛圍核心組件和可選組件。
核心組件中的主組件負(fù)責(zé)控制粒子系統(tǒng)的基本參數(shù),比如生命周期、粒子存活時(shí)間等,發(fā)射組件負(fù)責(zé)控制粒子的發(fā)射。
可選組件實(shí)現(xiàn)了不同的功能,比如形狀組件可以控制發(fā)射器的形狀,Velocity Over Lifetime組件控制粒子生命周期中的速度變化等等。使用者可以根據(jù)想要的效果只啟用對(duì)應(yīng)的可選組件。
Shader Effects
對(duì)于一些特殊的,或者不具有通用性的特效,一種值得考慮的實(shí)現(xiàn)方式就是使用Shader
在一些情況下,Shader實(shí)現(xiàn)會(huì)比使用通用方式性能更好,或得到特別的表現(xiàn)效果。
9
借助Crab提供的渲染階段和渲染管線上的擴(kuò)展能力,使用者可以自由實(shí)現(xiàn)期望的Shader效果。
下為使用渲染階段實(shí)現(xiàn)Crab文字內(nèi)流體效果的部分代碼示意:
this.scene.renderProcess
.addStage(advectVelPass)
.addStage(disturbVelPass)
.addStage(advergencePass)
.addStage(iteraGroup)
.addStage(applyForcePass)
.addStage(disturbDyePass)
.addStage(advectDyePass)
.addStage(bloomGroup)
.addStage(displayPass);
四、游戲化動(dòng)效的應(yīng)用與實(shí)踐
對(duì)于一個(gè)場(chǎng)景的游戲化動(dòng)效,里面不同的原子動(dòng)效,研發(fā)會(huì)接收到來自上游的許多不同種類的交付素材。其中既有來自平面動(dòng)效交付鏈路的Lottie、序列幀、AE參數(shù)等,也有來自游戲化動(dòng)效交付鏈路的3D模型、粒子特效和模型材質(zhì)等。
這么多種類的來自不同鏈路的動(dòng)效交付,給我們帶來了幾個(gè)挑戰(zhàn):
- 混合播放
交付的素材中既會(huì)有3D模型等游戲化素材, 又會(huì)有Lottie, 序列幀等平面動(dòng)效素材, 如何保證這些不同來源的資產(chǎn)可以一同展示?
- 素材生產(chǎn)
一些動(dòng)效素材, 比如粒子特效參數(shù), 材質(zhì)參數(shù)等, 必須基于動(dòng)效渲染引擎進(jìn)行所見即所得的編輯來生產(chǎn), 如何實(shí)現(xiàn)?
- 素材轉(zhuǎn)換
FBX模型,、序列幀等素材,無在runtime直接使用的表現(xiàn)不佳,需要進(jìn)行格式轉(zhuǎn)換。每種類型的素材需要的轉(zhuǎn)換方式不同,如何降低轉(zhuǎn)換過程中的心智負(fù)擔(dān)?
交付痛點(diǎn)的解決方案
為了解決上述的痛點(diǎn),我們?yōu)镃rab開發(fā)了一個(gè)編輯器,編輯器提供了素材的導(dǎo)入導(dǎo)出、格式轉(zhuǎn)換、編輯以及預(yù)覽功能。
上游提供的任意已經(jīng)支持的動(dòng)效素材類型,經(jīng)過編輯器中可選的格式轉(zhuǎn)換以及編輯處理之后,都可以導(dǎo)出為可以在Crab直接進(jìn)行使用的動(dòng)效素材,而編輯器提供的預(yù)覽功能也可以保證導(dǎo)出的原子動(dòng)效的效果符合設(shè)計(jì)同學(xué)的預(yù)期,將走查問題盡量前置。
?
交付示例
以材質(zhì)交付為例,當(dāng)在編輯器的屬性面板編輯材質(zhì)參數(shù)時(shí),主視區(qū)的預(yù)覽效果可以實(shí)時(shí)更新,當(dāng)設(shè)計(jì)師編輯完成后,可以直接導(dǎo)出為研發(fā)在runtime時(shí)可用的材質(zhì)素材。
五、游戲化動(dòng)效的性能指標(biāo)和調(diào)優(yōu)
Crab內(nèi)部執(zhí)行渲染操作時(shí),會(huì)執(zhí)行一些基礎(chǔ)的性能優(yōu)化,比如資產(chǎn)在顯存創(chuàng)建后,及時(shí)銷毀資產(chǎn)在內(nèi)存的緩存,減少不必要的WebGL上下文切換,如活躍shader program切換、混合模式切換等。
除了Crab引擎內(nèi)部的優(yōu)化,在特定場(chǎng)景的調(diào)優(yōu)對(duì)一個(gè)游戲化動(dòng)效的性能常具有更顯著的影響。在進(jìn)行游戲化動(dòng)效開發(fā)時(shí),主要關(guān)注的性能指標(biāo)有以下幾個(gè):幀率、Draw Call數(shù)量,三角形數(shù)量,內(nèi)存占用以及卡頓率。
- 幀率:我們可以通過鎖定引擎幀率的方式,控制每秒執(zhí)行的邏輯計(jì)算和渲染計(jì)算的數(shù)量,從而減少對(duì)計(jì)算資源的占用,提供頁面整體的性能。
- Draw Call數(shù)量:我們可以通過視錐剪裁或使用實(shí)例化渲染的方式來減少Draw Call的數(shù)量。比如當(dāng)場(chǎng)景中存在N個(gè)相同模型的時(shí)候,使用實(shí)例化渲染可以將Draw Call的數(shù)量從N次減少到一次。
- 三角形數(shù)量:一幀渲染使用的三角形數(shù)量對(duì)性能影響很大,對(duì)一些不太重要或不必要的場(chǎng)景物體,我們會(huì)盡量減少它包含的三角形數(shù)量,比如使用單面片或十字面片,可將物體所需的三角形數(shù)量降低至10個(gè)內(nèi)。
- 內(nèi)存占用:要降低內(nèi)存占用,主要可以通過減少貼圖分辨率或使用壓縮貼圖的方式來進(jìn)行優(yōu)化,另外也要注意使用網(wǎng)格的物體三角形的數(shù)量不要爆炸,否則也會(huì)對(duì)內(nèi)存占用帶來負(fù)面影響。
- 卡頓率:對(duì)于卡頓率,我們一般可以通過優(yōu)化shader中的邏輯實(shí)現(xiàn)進(jìn)行優(yōu)化,比如在shader中要盡量避免動(dòng)態(tài)循環(huán)次數(shù)的循環(huán)語句和條件語句的使用。
以上就是本篇文章的全部內(nèi)容,介紹了自研的Crab動(dòng)效渲染引擎,以及Crab在實(shí)際業(yè)務(wù)的使用中落地過的具體動(dòng)效方案,交付方案和性能調(diào)優(yōu)方案。希望能給看到這里的你帶來一些收獲,如果有任何問題或建議,也歡迎留言,不吝賜教。
- END -
