- cocos creator 版本3.8.4
关键点
dissolveThreshold: { value: 0.8, editor: { slide: true, range: [0, 1], step: 0.01, displayName: dissolveThreshold } }定义溶解滑条uniform Constants { vec4 albedo; vec4 albedoScaleAndCutoff; vec4 pbrParams; float opacity; float dissolveThreshold; };定义完成后必须要声明,才能使用noiseTexture: { value: white, target: noiseMap, visible: true, editor: { displayName: "Noise Map", type: texture } }这里定义噪声图,并且只有embeddedMacros: { USE_NOISE_MAP: true } # 强制启用宏添加强制使用宏才可以显式在材质里选择对应的噪声图- 所谓噪声图就是一张包含随机灰度值的纹理(通常是 灰度图),每个像素的RGB值相同(R=G=B)。
- 这里是核心部分,噪音值小于溶解dissolveThreshold的部分就不展示
#if USE_NOISE_MAP
float noise = texture(noiseMap, NOISE_UV).r;
#else
// 回退到数学噪声
float noise = randomNoise(gl_FragCoord.xy / 100.0);
#endif
if(noise < dissolveThreshold) {
discard;
}
// 边缘过渡(可选)
float edgeWidth = 0.1;
float edge = smoothstep(dissolveThreshold, dissolveThreshold + edgeWidth, noise);
baseColor.a *= (noise < dissolveThreshold + edgeWidth) ? edge : 1.0;
return baseColor;
6. 完整代码
// Effect Syntax Guide: https://docs.cocos.com/creator/manual/zh/shader/index.html
CCEffect %{
techniques:
- name: opaque
passes:
- vert: standard-vs
frag: standard-fs
embeddedMacros: { USE_NOISE_MAP: true } # 强制启用宏
properties: &props
mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } }
mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, linear: true, editor: { displayName: Albedo, type: color } }
opacity: { value: 1.0, editor: { slide: true, range: [0, 1], step: 0.01, displayName: Opacity } }
dissolveThreshold: { value: 0.8, editor: { slide: true, range: [0, 1], step: 0.01, displayName: dissolveThreshold } }
noiseTexture: {
value: white,
target: noiseMap,
visible: true,
editor: {
displayName: "Noise Map",
type: texture
}
}
albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz }
alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST, slide: true, range: [0, 1.0], step: 0.001 } }
roughness: { value: 0.8, target: pbrParams.y, editor: { slide: true, range: [0, 1.0], step: 0.001 } }
metallic: { value: 0.6, target: pbrParams.z, editor: { slide: true, range: [0, 1.0], step: 0.001 } }
- &forward-add
vert: standard-vs
frag: standard-fs
phase: forward-add
propertyIndex: 0
embeddedMacros: { CC_FORWARD_ADD: true }
depthStencilState:
depthFunc: equal
depthTest: true
depthWrite: false
blendState:
targets:
- blend: true
blendSrc: src_alpha # 源颜色 = 当前片元Alpha * 当前颜色
blendDst: one_minus_src_alpha # 目标颜色 = (1 - 当前Alpha) * 原有颜色
blendSrcAlpha: src_alpha # 源Alpha = 当前Alpha
blendDstAlpha: one_minus_src_alpha # 目标Alpha = (1 - 当前Alpha)
- &shadow-caster
vert: shadow-caster-vs
frag: shadow-caster-fs
phase: shadow-caster
propertyIndex: 0
rasterizerState:
cullMode: front
properties:
mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, editor: { displayName: Albedo, type: color } }
albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz }
alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } }
mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } }
- name: transparent
passes:
- vert: standard-vs
frag: standard-fs
embeddedMacros: { CC_FORCE_FORWARD_SHADING: true }
depthStencilState:
depthTest: true
depthWrite: false
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
blendDstAlpha: one_minus_src_alpha
properties: *props
- *forward-add
- *shadow-caster
}%
CCProgram shared-ubos %{
uniform Constants {
vec4 albedo;
vec4 albedoScaleAndCutoff;
vec4 pbrParams;
float opacity;
float dissolveThreshold;
};
}%
CCProgram macro-remapping %{
// ui displayed macros
#pragma define-meta USE_TWOSIDE
#pragma define-meta USE_VERTEX_COLOR
#define CC_SURFACES_USE_TWO_SIDED USE_TWOSIDE
#define CC_SURFACES_USE_VERTEX_COLOR USE_VERTEX_COLOR
}%
CCProgram surface-vertex %{
#define CC_SURFACES_VERTEX_MODIFY_WORLD_POS
vec3 SurfacesVertexModifyWorldPos(in SurfacesStandardVertexIntermediate In)
{
return In.worldPos;
}
#define CC_SURFACES_VERTEX_MODIFY_WORLD_NORMAL
vec3 SurfacesVertexModifyWorldNormal(in SurfacesStandardVertexIntermediate In)
{
return In.worldNormal.xyz;
}
#define CC_SURFACES_VERTEX_MODIFY_UV
void SurfacesVertexModifyUV(inout SurfacesStandardVertexIntermediate In)
{
}
}%
CCProgram surface-fragment %{
// 声明噪声贴图
#if USE_NOISE_MAP
uniform sampler2D noiseMap;
#pragma define-meta NOISE_UV options([v_uv, v_uv1, v_worldPos.xy])
#endif
// 伪随机噪声函数(无需贴图)
float randomNoise(vec2 uv) {
return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453);
}
#if USE_ALBEDO_MAP
uniform sampler2D albedoMap;
#pragma define-meta ALBEDO_UV options([v_uv, v_uv1])
#endif
#if USE_ALPHA_TEST
#pragma define-meta ALPHA_TEST_CHANNEL options([a, r])
#endif
#define CC_SURFACES_FRAGMENT_MODIFY_BASECOLOR_AND_TRANSPARENCY
vec4 SurfacesFragmentModifyBaseColorAndTransparency()
{
vec4 baseColor = albedo;
#if USE_ALBEDO_MAP
vec4 texColor = texture(albedoMap, ALBEDO_UV);
texColor.rgb = SRGBToLinear(texColor.rgb);
baseColor *= texColor;
#endif
#if USE_ALPHA_TEST
if (baseColor.ALPHA_TEST_CHANNEL < albedoScaleAndCutoff.w) discard;
#endif
baseColor.rgb *= albedoScaleAndCutoff.xyz;
baseColor.a *= opacity;
vec2 uv = gl_FragCoord.xy / vec2(1024.0, 768.0);
// float noise = randomNoise(uv * 10.0);
#if USE_NOISE_MAP
float noise = texture(noiseMap, NOISE_UV).r;
#else
// 回退到数学噪声
float noise = randomNoise(gl_FragCoord.xy / 100.0);
#endif
if(noise < dissolveThreshold) {
discard;
}
// 边缘过渡(可选)
float edgeWidth = 0.1;
float edge = smoothstep(dissolveThreshold, dissolveThreshold + edgeWidth, noise);
baseColor.a *= (noise < dissolveThreshold + edgeWidth) ? edge : 1.0;
return baseColor;
}
#define CC_SURFACES_FRAGMENT_ALPHA_CLIP_ONLY
void SurfacesFragmentAlphaClipOnly()
{
#if USE_ALPHA_TEST
float alpha = albedo.ALPHA_TEST_CHANNEL;
#if USE_VERTEX_COLOR
alpha *= FSInput_vertexColor.a;
#endif
#if USE_ALBEDO_MAP
alpha = texture(albedoMap, ALBEDO_UV).ALPHA_TEST_CHANNEL;
#endif
if (alpha < albedoScaleAndCutoff.w) discard;
#endif
}
#define CC_SURFACES_FRAGMENT_MODIFY_WORLD_NORMAL
vec3 SurfacesFragmentModifyWorldNormal()
{
return normalize(FSInput_worldNormal);
}
#define CC_SURFACES_FRAGMENT_MODIFY_EMISSIVE
vec3 SurfacesFragmentModifyEmissive()
{
return vec3(0.0, 0.0, 0.0);
}
#define CC_SURFACES_FRAGMENT_MODIFY_PBRPARAMS
vec4 SurfacesFragmentModifyPBRParams()
{
// ao, roughness, metallic, specularIntensity
return vec4(1.0, pbrParams.y, pbrParams.z, 0.5);
}
}%
CCProgram standard-vs %{
precision highp float;
// 1. surface internal macros, for technique usage or remapping some user (material) macros to surface internal macros
#include <macro-remapping>
#include <surfaces/effect-macros/common-macros>
// 2. common include with corresponding shader stage, include before surface functions
#include <surfaces/includes/common-vs>
// 3. user surface functions that can use user (effect) parameters (ubo Constants)
// see surfaces/default-functions/xxx.chunk
#include <shared-ubos>
#include <surface-vertex>
// 4. surface include with corresponding shader stage and shading-model (optional)
#include <surfaces/includes/standard-vs>
// 5. shader entry with corresponding shader stage and technique usage/type
#include <shading-entries/main-functions/render-to-scene/vs>
}%
CCProgram shadow-caster-vs %{
precision highp float;
#include <surfaces/effect-macros/render-to-shadowmap>
#include <surfaces/includes/common-vs>
#include <shared-ubos>
#include <surface-vertex>
#include <shading-entries/main-functions/render-to-shadowmap/vs>
}%
CCProgram standard-fs %{
// shading-model : standard
// lighting-model : standard (isotropy / anisotropy pbr)
// shader stage : fs
// technique usage/type : render-to-scene
precision highp float;
// 1. surface internal macros, for technique usage or remapping some user (material) macros to surface internal macros
#include <macro-remapping>
#include <surfaces/effect-macros/common-macros>
// 2. common include with corresponding shader stage, include before surface functions
#include <surfaces/includes/common-fs>
// 3. user surface functions that can use user (effect) parameters (ubo Constants)
// see surfaces/default-functions/xxx.chunk
#include <shared-ubos>
#include <surface-fragment>
// 4. lighting-model (optional)
#include <lighting-models/includes/standard>
// 5. surface include with corresponding shader stage and shading-model (optional)
#include <surfaces/includes/standard-fs>
// 6. shader entry with corresponding shader stage and technique usage/type
#include <shading-entries/main-functions/render-to-scene/fs>
}%
CCProgram shadow-caster-fs %{
precision highp float;
#include <surfaces/effect-macros/render-to-shadowmap>
#include <surfaces/includes/common-fs>
#include <shared-ubos>
#include <surface-fragment>
#include <shading-entries/main-functions/render-to-shadowmap/fs>
}%