在上一章裡,我們成功地利用了自定義 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