Cesium開發(fā)高級篇 | 05場景后期處理

為實現(xiàn)三維模型的更炫最欠、更酷、更美觀惩猫,Cesium在1.46的版本中新增了場景的后期處理(Post Processing)功能芝硬,包括模型描邊、黑白圖轧房、明亮度調(diào)整拌阴、夜市效果、環(huán)境光遮蔽锯厢,也包括雷達掃描皮官、原型擴散等一些特效。今天我們來學習一下場景后期處理的基礎(chǔ)知識和實現(xiàn)流程实辑。

場景后期處理流程

場景的后期處理這個詞比較陌生捺氢,但說起照片的PS大家都很熟悉,這兩個過程非常類似剪撬。日常生活中我們拍攝完照片之后摄乒,發(fā)現(xiàn)太亮或太暗,又或者是皮膚不夠白、臉上痘痘明顯馍佑,我們可以調(diào)整亮度斋否、修復一下嫩白的臉蛋,經(jīng)過幾波操作之后拭荤,得到了一張我們非常滿意的照片茵臭。

image210.png

我們可以把照片的修復過程簡單理解成場景的后期處理過程,修圖的過程就比喻成對三維場景中初始渲染的效果進行再處理舅世,比如添加物體描邊旦委、明暗度調(diào)整、夜市效果等雏亚,最終把綜合之后的效果在場景中渲染出來缨硝。Cesium中的場景后期處理的大概流程如下圖所示:

image209.png

下面結(jié)合Cesium本身的PostProcess類,詳細的說明一下處理流程:
第一步:通過PostProcessStageLibrary創(chuàng)建一個或者多個后處理效果對象罢低,得到多個PostProcessStage或PostProcessStageComposite查辩;
第二步:將他們加入到PostProcessStageCollection對象中,并設(shè)置PostProcessStage或PostProcessStageComposite一些參數(shù)网持,如uniforms宜岛;
第三步:PostProcessStageCollection對象就會按照加入的順序進行屏幕后期處理,在所有的效果都處理完畢后翎碑,最后繪制到屏幕上谬返。
當然也可以省略第一步,直接利用PostProcessStageCollection實例化對象中已有的處理效果去實現(xiàn)日杈,如ambientOcclusion、bloom佑刷、fxaa莉擒。

場景后期處理相關(guān)類

上述提到了PostProcess類,基本上涉及到4個類文件瘫絮,具體每個類的作用又是什么呢涨冀?我們來說明一下。
(1)PostProcessStage
對應(yīng)于某個具體的后期處理效果麦萤,它的輸入為場景渲染圖或者上一個后期處理的結(jié)果圖鹿鳖,輸出結(jié)果是一張?zhí)幚砗蟮膱D片。

// Simple stage to change the colorvar 
fs =
    'uniform sampler2D colorTexture;\n' +
    'varying vec2 v_textureCoordinates;\n' +
    'uniform float scale;\n' +
    'uniform vec3 offset;\n' +
    'void main() {\n' +
    '    vec4 color = texture2D(colorTexture, v_textureCoordinates);\n' +
    '    gl_FragColor = vec4(color.rgb * scale + offset, 1.0);\n' +
    '}\n';
scene.postProcessStages.add(new Cesium.PostProcessStage({
    fragmentShader : fs,
    uniforms : {
        scale : 1.1,
        offset : function() {
            return new Cesium.Cartesian3(0.1, 0.2, 0.3);
        }
    }}));

fragmentShader:片源著色器代碼字符串壮莹,它是GLSL代碼語言翅帜,需要成對配置頂點著色器和片元著色器。
uniforms:片源著色器代碼字符串中需要在前端傳入的變量命满。
(2)PostProcessStageComposite
一個集合對象涝滴,按順序存儲了不同的場景處理對象,存儲類型為PostProcessStage或者PostProcessStageComposite的元素,并存儲在stages屬性中歼疮。

// Example 1: separable blur filter
// The input to blurXDirection is the texture rendered to by the scene or the output of the previous stage.
// The input to blurYDirection is the texture rendered to by blurXDirection.
scene.postProcessStages.add(new Cesium.PostProcessStageComposite({
    stages : [blurXDirection, blurYDirection]}));

(3)PostProcessStageLibrary
負責創(chuàng)建具體的后期處理效果杂抽,提供了一些創(chuàng)建常用場景特效的方法,包括createBlackAndWhiteStage-黑色和白色漸變渲染韩脏、createBlurStage-高斯模缩麸、createBrightnessStage-紋理飽和、createDepthOfFieldStage-景深效果等赡矢,創(chuàng)建返回的結(jié)果是PostProcessStageComposite或者PostProcessStage類型匙睹。相對來說比較簡單,直接調(diào)用即可济竹。

var stages = viewer.scene.postProcessStages;
  var silhouette = stages.add(
    Cesium.PostProcessStageLibrary.createSilhouetteStage()
  );

(4)PostProcessStageCollection
是一個集合類型的類痕檬,負責管理和維護放到集合中的PostProcessStage或PostProcessStageComposite類型對象,實例化對象可通過viewer.scene.postProcessStages直接獲取送浊,提供了一些常用的方法梦谜,如add、contains袭景、destroy唁桩、remove等。
但需要注意的是耸棒,該集合中也設(shè)定了三個ambientOcclusion荒澡、bloom、fxaa效果与殃,如果此類中的環(huán)境光遮擋-ambientOcclusion或發(fā)光效果-bloom被啟用单山,它們將在所有其他階段之前執(zhí)行,優(yōu)先級最高幅疼;如果近似抗鋸齒-fxaa被啟用米奸,它將在所有其他階段之后執(zhí)行,優(yōu)先級最低爽篷。

場景后期處理效果

Cesium為我們提供了一些默認的示例效果悴晰,但基本上可分為如下三類:
(1)利用PostProcessStageCollection集合類提供的三個效果
包括ambientOcclusion環(huán)境光遮擋、bloom發(fā)光效果逐工、fxaa近似抗鋸齒铡溪,我們挑選前兩個為例進行說明。

  • ambientOcclusion環(huán)境光遮擋
function updatePostProcess() {
  const ambientOcclusion =
    viewer.scene.postProcessStages.ambientOcclusion;
  ambientOcclusion.enabled =
    Boolean(viewModel.show) || Boolean(viewModel.ambientOcclusionOnly);
  ambientOcclusion.uniforms.ambientOcclusionOnly = Boolean(
    viewModel.ambientOcclusionOnly
  );
  ambientOcclusion.uniforms.intensity = Number(viewModel.intensity);
  ambientOcclusion.uniforms.bias = Number(viewModel.bias);
  ambientOcclusion.uniforms.lengthCap = Number(viewModel.lengthCap);
  ambientOcclusion.uniforms.stepSize = Number(viewModel.stepSize);
  ambientOcclusion.uniforms.blurStepSize = Number(
    viewModel.blurStepSize
  );
}

image212.png

沒有開啟AO效果如上圖一泪喊,開啟AO效果如上圖二棕硫,單純的AO圖如上圖三

  • bloom發(fā)光效果
function updatePostProcess() {
  const bloom = viewer.scene.postProcessStages.bloom;
  bloom.enabled = Boolean(viewModel.show);
  bloom.uniforms.glowOnly = Boolean(viewModel.glowOnly);
  bloom.uniforms.contrast = Number(viewModel.contrast);
  bloom.uniforms.brightness = Number(viewModel.brightness);
  bloom.uniforms.delta = Number(viewModel.delta);
  bloom.uniforms.sigma = Number(viewModel.sigma);
  bloom.uniforms.stepSize = Number(viewModel.stepSize);
}

image214.png

(2)直接調(diào)用PostProcessStageLibrary中提供的方法去渲染場景特效
Cesium在場景處理庫中默認為我們提供了如下8個效果,其實也是非常簡單的窘俺,直接調(diào)用即可饲帅。

下面是一個切換動畫小人效果的簡單示例:

const stages = viewer.scene.postProcessStages;
const silhouette = stages.add(
  Cesium.PostProcessStageLibrary.createSilhouetteStage()
);
const blackAndWhite = stages.add(
  Cesium.PostProcessStageLibrary.createBlackAndWhiteStage()
);
const brightness = stages.add(
  Cesium.PostProcessStageLibrary.createBrightnessStage()
);
const nightVision = stages.add(
  Cesium.PostProcessStageLibrary.createNightVisionStage()
);

function updatePostProcess() {
  silhouette.enabled = Boolean(viewModel.silhouette);
  silhouette.uniforms.color = Cesium.Color.YELLOW;
  blackAndWhite.enabled = Boolean(viewModel.blackAndWhiteShow);
  blackAndWhite.uniforms.gradations = Number(
    viewModel.blackAndWhiteGradations
  );
  brightness.enabled = Boolean(viewModel.brightnessShow);
  brightness.uniforms.brightness = Number(viewModel.brightnessValue);
  nightVision.enabled = Boolean(viewModel.nightVisionShow);
}

物體描邊.gif

(3)編寫自定義Shader實現(xiàn)場景特效
要想實現(xiàn)自定義Shader复凳,不僅需要開發(fā)者了解頂點著色器和片元著色器,openGL灶泵,還需要會編寫GLSL(GL Shading Language)語言育八,通過自定義Shader可以表達更多的場景特效。關(guān)于GLSL編程語法赦邻,這里就不多贅述了髓棋,感興趣的可以查看其官網(wǎng)。下面是一個簡單的給動畫小人打馬賽克的示例:

const fragmentShaderSource = `
  uniform sampler2D colorTexture; 
  varying vec2 v_textureCoordinates; 
  const int KERNEL_WIDTH = 16; 
  void main(void) 
  { 
      vec2 step = czm_pixelRatio / czm_viewport.zw; 
      vec2 integralPos = v_textureCoordinates - mod(v_textureCoordinates, 8.0 * step); 
      vec3 averageValue = vec3(0.0); 
      for (int i = 0; i < KERNEL_WIDTH; i++) 
      { 
          for (int j = 0; j < KERNEL_WIDTH; j++) 
          { 
              averageValue += texture2D(colorTexture, integralPos + step * vec2(i, j)).rgb; 
          } 
      } 
      averageValue /= float(KERNEL_WIDTH * KERNEL_WIDTH); 
      gl_FragColor = vec4(averageValue, 1.0); 
  }
  `;
viewer.scene.postProcessStages.add(
  new Cesium.PostProcessStage({
    fragmentShader: fragmentShaderSource,
  })

圖片1.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惶洲,一起剝皮案震驚了整個濱河市按声,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恬吕,老刑警劉巖签则,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異铐料,居然都是意外死亡渐裂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門钠惩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柒凉,“玉大人,你說我怎么就攤上這事篓跛∠ダ蹋” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵愧沟,是天一觀的道長蔬咬。 經(jīng)常有香客問我,道長央渣,這世上最難降的妖魔是什么计盒? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮芽丹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘卜朗。我一直安慰自己拔第,他們只是感情好,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布场钉。 她就那樣靜靜地躺著蚊俺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逛万。 梳的紋絲不亂的頭發(fā)上泳猬,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼得封。 笑死埋心,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的忙上。 我是一名探鬼主播拷呆,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼疫粥!你這毒婦竟也來了茬斧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤梗逮,失蹤者是張志新(化名)和其女友劉穎项秉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慷彤,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡娄蔼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞬欧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贷屎。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖艘虎,靈堂內(nèi)的尸體忽然破棺而出唉侄,到底是詐尸還是另有隱情,我是刑警寧澤野建,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布属划,位于F島的核電站,受9級特大地震影響候生,放射性物質(zhì)發(fā)生泄漏同眯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一唯鸭、第九天 我趴在偏房一處隱蔽的房頂上張望须蜗。 院中可真熱鬧,春花似錦目溉、人聲如沸明肮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柿估。三九已至,卻和暖如春陷猫,著一層夾襖步出監(jiān)牢的瞬間秫舌,已是汗流浹背的妖。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留足陨,地道東北人嫂粟。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像钠右,于是被迫代替她去往敵國和親赋元。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容