MF_PS_Style_Shadow

定义 function input。

公开到库(可选)

Shadow代码:
- /**
- PS图层样式投影效果
- @param {UVs} texture coordinate
- @param {Texture} texture object
- @param {TextureSize} 纹理大小(x, y)
- @param {ShadowRGBA} 投影颜色与不透明度
- @param {ShadowRotate} 投影角度
- @param {ShadowLength} 投影距离
- @param {ShadowSize} 投影大小
- @param {BorderThreshold} 边界UVs阈值(左, 上, 右, 下)
- */
- float4 Shadow(float2 UVs, Texture2D Texture, float2 TextureSize, float4 ShadowRGBA, float ShadowRotate, half ShadowLength, half ShadowSize, float4 BorderThreshold=0.001) {
- const float PI = acos(-1);
- // 单位像素
- float2 TexturePixel = 1 / TextureSize;
- // 角度
- float Angle = 360 * ShadowRotate;
- // 弧度
- float Degrees = Angle / 180 * PI;
- // 阴影反向方位(单位向量)
- float2 Direction = TexturePixel * float2(cos(Degrees), sin(Degrees));
-
- class Function {
- Texture2D Texture;
- SamplerState TextureSampler;
- float4 ShadowRGBA;
- float2 Position;
- float BorderThresholdLeft;
- float BorderThresholdTop;
- float BorderThresholdRight;
- float BorderThresholdBottom;
-
- float PI;
- float2 TexturePixel;
-
- // 阴影颜色
- float3 ShadowColor(float3 Color) {
- // 如果需要与颜色混合,在此修改返回值,如下式 正片叠底。
- // return this.ShadowRGBA.rgb * Color;
- return this.ShadowRGBA.rgb;
- }
-
- // 混合
- float3 Blend(float3 base, float3 blend, float alpha) {
- // 如果使用了混合模式,把 blend 按混合公式计算一次,如下式 正片叠底。
- // blend = base * blend;
- return lerp(base, blend, alpha);
- }
-
- // 纹理采样
- float4 TextureSample(float2 UVs) {
- // 如果需要 alpha 通道反向,在此修改。
- return Texture2DSampleLevel(this.Texture, this.TextureSampler, UVs, 0).xyzw;
- }
-
- float4 GetShadowRGBA(float2 UVs) {
- // 当前像素点 RGBA
- float4 TextureRGBA = this.TextureSample(UVs);
- // 阴影反向方位 UVs
- float2 PositionUVs = UVs + this.Position;
- // 阴影反向方位 UVs 超出了 0 - 1 的范围则不计算
- if (PositionUVs.x < this.BorderThresholdLeft || PositionUVs.x > this.BorderThresholdRight || PositionUVs.y < this.BorderThresholdTop || PositionUVs.y > this.BorderThresholdBottom) {
- return TextureRGBA;
- }
- // 阴影反向方位像素点RGBA
- float4 PositionRGBA = this.TextureSample(PositionUVs);
- // 阴影透明度
- float ShadowOpacity = PositionRGBA.a * this.ShadowRGBA.a;
- if (ShadowOpacity <= 0) {
- return TextureRGBA;
- }
- // 当前像素点混合后的结果色
- // this.ShadowRGBA.rgb 为 base 固有色
- // TextureRGBA.rgb 为 blend 固有色
- // TextureRGBA.a 为 alpha
- float3 ShadowBlendColor = this.Blend(this.ShadowColor(PositionRGBA.rgb) * ShadowOpacity, TextureRGBA.rgb, TextureRGBA.a);
- // 当前像素点混合后的透明度
- float ShadowBlendOpacity = ShadowOpacity + TextureRGBA.a - ShadowOpacity * TextureRGBA.a;
- // 当前像素点混合后的RGBA
- return float4(ShadowBlendColor / ShadowBlendOpacity, ShadowBlendOpacity);
- }
-
- float Calculate1DGaussian(float x) {
- return exp(-0.5 * pow(this.PI * x, 2));
- }
-
- float4 GetShadowSizeRGBA(float2 UVs, half ShadowSize) {
- // 当前像素点 RGBA
- float4 TextureRGBA = this.TextureSample(UVs);
- // 投影大小范围内像素颜色累加
- float4 RGBASum = float4(0, 0, 0, 0);
- // 投影大小范围内像素的权重
- float WeightSum = 0;
- for (half x = -ShadowSize; x <= ShadowSize; x++) {
- for (half y = -ShadowSize; y <= ShadowSize; y++) {
- float Weight = this.Calculate1DGaussian(x / ShadowSize) * this.Calculate1DGaussian(y / ShadowSize);
- WeightSum += Weight;
- // 阴影偏移 UVs
- float2 OffsetUVs = UVs + float2(x, y) * this.TexturePixel + this.Position;
- if (OffsetUVs.x < this.BorderThresholdLeft || OffsetUVs.x > this.BorderThresholdRight || OffsetUVs.y < this.BorderThresholdTop || OffsetUVs.y > this.BorderThresholdBottom) {
- continue;
- }
- // 阴影偏移像素点 RGBA
- float4 OffsetRGBA = this.TextureSample(OffsetUVs);
- // 阴影透明度
- float Opacity = this.ShadowRGBA.a * OffsetRGBA.a;
- if (Opacity <= 0) {
- continue;
- }
- // 阴影结果色
- float4 RGBA = float4(this.ShadowColor(OffsetRGBA.rgb), Opacity);
- RGBASum += RGBA * Weight;
- }
- }
- // 模糊后的 RGBA
- float4 BlurRGBA = RGBASum / WeightSum;
- // 当前像素点混合后的结果色
- float3 Color = this.Blend(BlurRGBA.rgb * BlurRGBA.a, TextureRGBA.rgb, TextureRGBA.a);
- // 当前像素点混合后的透明度
- float Opacity = BlurRGBA.a + TextureRGBA.a - BlurRGBA.a * TextureRGBA.a;
- // 当前像素点混合后的RGBA
- return float4(Color / Opacity, Opacity);
- }
- }; // 注意要加分号
-
- // Function func;
- // func.Texture = Texture;
- // func.TextureSampler = TextureSampler;
- // func.ShadowRGBA = ShadowRGBA;
- // func.Position = ShadowLength * Direction;
- // func.BorderThresholdLeft = BorderThreshold.x;
- // func.BorderThresholdTop = BorderThreshold.y;
- // func.BorderThresholdRight = 1 - BorderThreshold.z;
- // func.BorderThresholdBottom = 1 - BorderThreshold.w;
- // func.PI = PI;
- // func.TexturePixel = TexturePixel;
- Function func = { Texture, TextureSampler, ShadowRGBA, ShadowLength * Direction, BorderThreshold.x, BorderThreshold.y, 1 - BorderThreshold.z, 1 - BorderThreshold.w, PI, TexturePixel };
- if (ShadowSize < 1) {
- return func.GetShadowRGBA(UVs);
- }
- return func.GetShadowSizeRGBA(UVs, round(ShadowSize));
- }
M_PS_Style_Shadow

修改 材质域 和 混合模式。

调用之前创建的材质函数。

材质函数调用方式。

如果之前没有公开到库,则使用 material function call 调用




设置尺寸,并指定效果材质。


由于字体所在画布大小为 300 * 100,这里要设置同步。

ShadowSize 为 0。

ShadowSize 为 10。

ShadowSize 为 20。

需要改颜色就修改 ShadowRGBA。

命名 RT_Equipment。

用于 UI 贴图,修改参数,这里大小使用1024。


命名 BP_Equipment

添加 场景捕获组件2D。

根据需要设置参数。

添加 骨骼网络体组件。

指定模型与动画。

调整好位置。


将 BP_Equipment 放入 Level,也可以在运行时动态生成。

由于 A 通道需要反向,所以之前的 Shadow 代码做如下改动:
- // 纹理采样
- float4 TextureSample(float2 UVs) {
- // 如果需要 alpha 通道反向,在此修改。
- float4 PixelRGBA = Texture2DSampleLevel(this.Texture, this.TextureSampler, UVs, 0).xyzw;
- return float4(PixelRGBA.rgb, 1 - PixelRGBA.a);
- }

假定使用 正片叠底,代码做如下改动。
- // 阴影颜色
- float3 ShadowColor(float3 Color) {
- // 如果需要与颜色混合,在此修改返回值,如下式 正片叠底。
- return this.ShadowRGBA.rgb * Color;
- }
也可以换成其他的混合模式,具体算法可以参考文章 《HLSL实现PS混合模式》。
