來點新花樣!使用噪聲圖實現不規則溶解效果

在上一章裡,我們成功地利用了自定義 Effect 和材質,替換了 Sprite 元件內建的材質。本章我們嘗試著對自定義的 Effect 做一些改造來實現

貼圖溶解效果

為了實現這種效果,需要標記出哪些畫素顯示、哪些畫素消失,比較好的辦法是用一張噪聲圖來給每一個畫素做標記,噪聲圖類似下圖。由於噪聲圖只有黑白灰三種顏色,黑白灰非均勻分佈,因此,可以利用黑透、白不透、灰半透的原理實現不規則溶解效果。

來點新花樣!使用噪聲圖實現不規則溶解效果

溶解效果最簡單的製作通常需要兩個引數:一個是

噪聲圖

,一個是

控制過濾黑/白畫素的閾值

。接下來,嘗試定義這兩個引數。

Cocos Effect

CCEffect

在之前的文章裡我們知道, CCEffect 包裹的是用 YAML 格式編輯的渲染流程描述清單,主要內容涉及與編輯器的互動以及與 CCProgram 的資料互動。CCEffect 的結構再次回顧一下,內容大致如下:

這是一個最最最基礎的 shader 宣告(例如:繪圖元件 Graphics 的 shader),如果要加入一個引數或者貼圖,就無法滿足。所以我們需要了解 pass 更多的引數。最常用的幾個引數如下:

pass 引數:

來點新花樣!使用噪聲圖實現不規則溶解效果

其中,blendState,depthStencilState,rasterizerState 瞭解即可。

properties 引數:

來點新花樣!使用噪聲圖實現不規則溶解效果

defalut values:

來點新花樣!使用噪聲圖實現不規則溶解效果

更多 pass 和 properties 引數可以參考下方參考文獻裡的“pass 可選配置引數”。

瞭解了一些重要的引數後,就可以開始定義引數了,在上一章最終修改後的 shader 上加入一些內容:

CCEffect %{

techniques:

- passes:

- vert: vs:vert

frag: fs:frag

blendState:

targets:

- blend: true

blendSrc: src_alpha

blendDst: one_minus_src_alpha

blendDstAlpha: one_minus_src_alpha

rasterizerState:

cullMode: none

properties:

u_dissolveMap: { value: white, editor: { tooltip: ‘噪聲貼圖’ } }

dissolveThreshold: { value: 0。5, editor: { range:[0, 1, 0。01], slide: true, tooltip: ‘溶解閾值’ } } # 此處定義的引數都必須指向 CCProgram 處對應宣告的 uniform

}%

CCProgram vs %{

precision highp float;

#include

in vec3 a_position;

in vec2 a_texCoord;

in vec4 a_color;

out vec4 color;

out vec2 uv0;

vec4 vert () {

vec4 pos = vec4(a_position, 1);

pos = cc_matViewProj * pos;

uv0 = a_texCoord;

color = a_color;

return pos;

}

}%

CCProgram fs %{

precision highp float;

in vec4 color;

uniform Dissolve{

float dissolveThreshold;// 熔岩閥值[0, 1];

};

#ifUSE_TEXTURE

in vec2 uv0;

uniform sampler2D u_dissolveMap;// 熔岩形狀的紋理;

#pragmabuiltin(local)

layout(set = 2, binding = 10) uniform sampler2D cc_spriteTexture;

#endif

vec4 frag () {

vec4 o = vec4(1, 1, 1, 1);

#ifUSE_TEXTURE

o *= texture(cc_spriteTexture, uv0);

#endif

o *= color;

return o;

}

}%

接著,回到編輯器,選擇材質,就可以看到新增了兩個可調整引數:

來點新花樣!使用噪聲圖實現不規則溶解效果

關聯噪聲後,根據溶解閾值,處理溶解度:

CCEffect %{

techniques:

- passes:

- vert: vs:vert

frag: fs:frag

blendState:

targets:

- blend: true

blendSrc: src_alpha

blendDst: one_minus_src_alpha

blendDstAlpha: one_minus_src_alpha

rasterizerState:

cullMode: none

properties:

u_dissolveMap: { value: white, editor: { tooltip: ‘噪聲貼圖’ } }

dissolveThreshold: { value: 0。5, editor: { range:[0, 1, 0。01], slide: true, tooltip: ‘溶解閾值’ } } # 此處定義的引數都必須指向 CCProgram 處對應宣告的 uniform

}%

CCProgram vs %{

precision highp float;

#include

in vec3 a_position;

in vec2 a_texCoord;

in vec4 a_color;

out vec4 color;

out vec2 uv0;

vec4 vert () {

vec4 pos = vec4(a_position, 1);

pos = cc_matViewProj * pos;

uv0 = a_texCoord;

color = a_color;

return pos;

}

}%

CCProgram fs %{

precision highp float;

in vec4 color;

uniform Dissolve{

float dissolveThreshold;// 熔岩閥值[0, 1];

};

#ifUSE_TEXTURE

in vec2 uv0;

uniform sampler2D u_dissolveMap;// 熔岩形狀的紋理;

#pragmabuiltin(local)

layout(set = 2, binding = 10) uniform sampler2D cc_spriteTexture;

#endif

vec4 frag () {

vec4 o = vec4(1, 1, 1, 1);

float value = 1。0;

#ifUSE_TEXTURE

vec4 dissolveMap = texture(u_dissolveMap, uv0); // 如果顏色的 r 分量小於閥值,將這個著色操作丟棄;

value *= dissolveMap。r;

#endif

if (value

discard; // 將小於閾值的片段丟棄,形成溶解

}

#ifUSE_TEXTURE

o *= texture(cc_spriteTexture, uv0); // 與原紋理混合;

#endif

o *= color;

if (value

o = vec4(0。9, 0。6, 0。3, o。a); // 溶解的邊緣設定一個邊緣過度色

}

return o;

}

}%

最後,我將原圖替換上 Cocos logo,將閾值調整為 0。2,畫面呈現的效果如下:

來點新花樣!使用噪聲圖實現不規則溶解效果

如果想要在執行時修改閾值,可以採用如下方法:

到這裡為止,我們就完成了一個 shader 的改造,看起來是不是很簡單。入門 shader 需要我們不斷去嘗試,所以大家在學習的時候一定要多去嘗試一些 shader 的改造,網上也有很多例子,都可以拿來照貓畫虎試上一試。

內容參考:

pass 可選配置引數:

https://docs。cocos。com/creator/3。2/manual/zh/material-system/pass-parameter-list。html

Cocos Shader 基礎入門系列

···更新中···

該系列教程

影片版

已更新至 EP07

TAG: vec4coloruv0引數uniform