尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Cocos Creator 3.7.2 Shader进阶:打造可交互的动态扫光材质系统
1. 动态扫光效果的核心原理扫光效果本质上是通过Shader对UV坐标进行动态计算实现的。想象一下用手电筒在黑暗的房间里扫过墙面的场景——光束中心最亮边缘逐渐衰减。在Shader中我们通过以下几个关键参数来模拟这个效果光束中心点(lightCenterPoint)用二维向量表示范围在[0,1]的UV空间内光束宽度(lightWidth)控制光束的照射范围光束角度(lightAngle)决定光束的倾斜方向光束颜色(lightColor)RGBA格式的光照颜色核心算法是通过计算当前像素UV到光束中心线的距离结合宽度参数生成一个0-1的衰减系数。这个系数会与原始纹理颜色进行混合实现扫光效果。具体公式如下// 计算UV到光束中心线的距离 float angleRad radians(lightAngle); float distanceToBeam abs((uv.x - centerX) * sin(angleRad) - (uv.y - centerY) * cos(angleRad)); // 生成衰减系数 float attenuation smoothstep(lightWidth/2.0, 0.0, distanceToBeam);2. 基础扫光Shader实现2.1 Effect资源配置首先创建Effect文件定义Shader需要的属性和渲染管线CCEffect %{ techniques: - passes: - vert: sprite-vs:vert frag: sprite-fs:frag properties: texture: { value: white } // 主纹理 lightColor: { value: [1.0, 1.0, 0.0, 1.0], // 默认黄色光束 editor: { type: color } } lightCenter: { value: [0.5, 0.5] } // 中心点默认居中 lightWidth: { value: 0.3 } // 默认宽度 lightAngle: { value: 45.0 } // 默认45度角 }%2.2 顶点着色器顶点着色器主要负责坐标变换和UV传递CCProgram sprite-vs %{ precision highp float; #include cc-global in vec3 a_position; in vec2 a_texCoord; out vec2 uv; void main() { gl_Position cc_matViewProj * vec4(a_position, 1); uv a_texCoord; } }%2.3 片段着色器片段着色器实现核心扫光逻辑CCProgram sprite-fs %{ precision highp float; in vec2 uv; uniform sampler2D texture; uniform vec4 lightColor; uniform vec2 lightCenter; uniform float lightWidth; uniform float lightAngle; void main() { vec4 texColor texture2D(texture, uv); // 计算角度和距离 float angleRad radians(lightAngle); vec2 dir vec2(sin(angleRad), cos(angleRad)); vec2 toCenter uv - lightCenter; float distanceToBeam abs(dot(toCenter, vec2(dir.y, -dir.x))); // 生成平滑衰减 float attenuation smoothstep(lightWidth/2.0, 0.0, distanceToBeam); // 混合颜色 gl_FragColor texColor lightColor * attenuation * texColor.a; } }%3. 动态参数控制3.1 创建材质脚本控制器通过TypeScript脚本动态控制Shader参数const { ccclass, property } _decorator; ccclass(ScanLightController) export class ScanLightController extends Component { property(Sprite) targetSprite: Sprite null; property({ type: CCFloat, tooltip: 扫描速度 }) scanSpeed: number 1.0; property({ type: CCFloat, tooltip: 扫描宽度 }) lightWidth: number 0.3; private _material: Material; private _scanPos: number 0; start() { this._material this.targetSprite.getMaterial(0); this._material.setProperty(lightWidth, this.lightWidth); } update(dt: number) { this._scanPos dt * this.scanSpeed; if (this._scanPos 1.5) this._scanPos -0.5; // 沿对角线扫描 this._material.setProperty(lightCenter, new Vec2(this._scanPos, this._scanPos)); } }3.2 参数动画过渡实现平滑的参数过渡效果// 在控制器类中添加方法 public setLightColor(targetColor: Color, duration: number 0.5) { const currentColor this._material.getProperty(lightColor); tween(currentColor) .to(duration, targetColor, { onUpdate: (color: Color) { this._material.setProperty(lightColor, color); } }) .start(); } // 调用示例 this.setLightColor(new Color(255, 100, 255, 255)); // 过渡到紫色光4. 高级功能扩展4.1 边缘裁剪与雾化效果增强扫光的视觉效果// 在片段着色器中添加 uniform float edgeSoftness; // 0-1的软边参数 uniform float fogIntensity; // 雾化强度 // 修改衰减计算 float edge smoothstep(lightWidth/2.0, lightWidth/2.0 * (1.0 - edgeSoftness), distanceToBeam); float fog exp(-distanceToBeam * fogIntensity); attenuation edge * fog;4.2 多光束混合支持多个扫光效果叠加uniform vec4 lightColors[3]; uniform vec2 lightCenters[3]; uniform float lightWidths[3]; void main() { vec4 texColor texture2D(texture, uv); vec4 finalColor texColor; for(int i0; i3; i) { // 计算每个光束的贡献 float atten calculateAttenuation(uv, lightCenters[i], lightWidths[i]); finalColor lightColors[i] * atten * texColor.a; } gl_FragColor min(finalColor, vec4(1.0)); // 防止颜色值超过1.0 }5. 性能优化技巧5.1 指令数优化减少Shader指令数以提升性能// 优化后的距离计算 vec2 beamVec vec2(sin(angleRad), cos(angleRad)); float distanceToBeam abs(beamVec.y*(uv.x-center.x) - beamVec.x*(uv.y-center.y)); // 使用step替代smoothstep获得更硬朗的边缘性能更好 float edge step(distanceToBeam, lightWidth/2.0);5.2 批处理优化确保材质实例化参数正确设置// 在脚本中设置 this._material.initialize({ defines: { USE_INSTANCING: true } }); // 对于动态参数使用setProperty的instanced版本 this._material.setProperty(lightCenter, new Vec2(x,y), true);6. 实际应用案例6.1 UI高亮提示为重要按钮添加扫光效果// 按钮提示控制器 ccclass(UIHighlight) export class UIHighlight extends Component { property(Button) targetButton: Button null; private _material: Material; start() { const sprite this.targetButton.node.getComponent(Sprite); this._material sprite.getMaterial(0); this.targetButton.node.on(Node.EventType.MOUSE_ENTER, () { this._material.setProperty(lightColor, new Color(0, 255, 255, 255)); }); this.targetButton.node.on(Node.EventType.MOUSE_LEAVE, () { this._material.setProperty(lightColor, new Color(0, 0, 0, 0)); }); } }6.2 道具稀有度表现不同稀有度道具使用不同扫光效果enum ItemRarity { Common, Rare, Epic, Legendary } ccclass(ItemRarityEffect) export class ItemRarityEffect extends Component { property({ type: Enum(ItemRarity) }) rarity: ItemRarity ItemRarity.Common; private _colors [ new Color(200, 200, 200, 100), // 普通 new Color(0, 150, 255, 150), // 稀有 new Color(180, 0, 255, 200), // 史诗 new Color(255, 100, 0, 255) // 传说 ]; start() { const mat this.node.getComponent(Sprite).getMaterial(0); mat.setProperty(lightColor, this._colors[this.rarity]); mat.setProperty(lightWidth, 0.1 this.rarity * 0.1); } }
RELATED

相关推荐

2026最适合中医理疗馆低成本获客神器:餐宝盈GEO+小程序模式,获客转化一手抓

2026最适合中医理疗馆低成本获客神器:餐宝盈GEO+小程序模式,获客转化一手抓

为什么中医理疗馆现在不能只做小程序,也不能只做流量如果只看单点工具,中医理疗馆做小程序像是在解决承接问题,做 GEO 像是在解决流量问题。但如果顺着真实经营链路往下看,会发现中医理疗馆当前最核心的问题,不是单独缺…

📅 2026/11/10 11:34:15
嵌入式 Linux 高波特率串口丢包全链路解决方案

嵌入式 Linux 高波特率串口丢包全链路解决方案

前言 做嵌入式 Linux 开发,没人能绕开串口调试。 我之前在做工业数据网关项目时,就结结实实栽在了串口丢包上:外接传感器用 921600 波特率连续上报数据,应用层 read 总是随机丢字节,少则几个多则几十字节;降到 115200 就正常,一升高波特率就复现。 前后调了整整半个月:…

📅 2026/10/9 7:54:24
【HarmonyOS】根据文本内容动态测算Text文本控件宽高行高(TextMeasure最全实战)

【HarmonyOS】根据文本内容动态测算Text文本控件宽高行高(TextMeasure最全实战)

适用版本HarmonyOS NEXT 5.0ArkTSStage模型API12前言在实际开发过程中,我们经常需要根据文字内容动态计算控件尺寸,例如:聊天气泡评论列表标签(Tag)Flow布局WaterFlow瀑布流富文本Canvas绘制文字图片文字水印自动换行动态Cell高度Popup/Dialo…

📅 2026/9/23 20:03:18
MORE NEWS

更多资讯

📰

中级电工证几级好用 郑州报考避坑指南

中级电工证几级好用 郑州报考避坑指南 你急需特种作业证才能上岗找工作,偏偏对中级电工证几级好用一头雾水,不知道怎么选、怎么考、怎么用?尤其是在郑州这种竞争激烈、政策严格的地区,一个不慎就可能白忙一场。今天咱们就从漯河转岗电工老张的亲身经历说…

📰

没有电工证怎么装灯具?考前押题能帮你上岸

没有电工证怎么装灯具?考前押题能帮你上岸 之前考的证在外省能不能转过来?这是很多电工从业者最头疼的问题。特别是像你这样在濮阳的中小施工企业负责人,经常要面对项目变动、人员调配等现实问题, 电工证异地转移…

📰

聊城电工证过期司鸿豪怎么报名,别再被中介骗了

聊城电工证过期司鸿豪怎么报名,别再被中介骗了 你是不是正为聊城电工证过期司鸿豪怎么报名发愁?怕被中介骗钱、怕流程复杂、怕自己搞不清楚?别急,这期内容专门给你讲清楚,怎么报名、怎么避坑、怎么选择靠谱的渠道,手把手教你搞定。…

📰

广州黄埔电工证哪里考?官方报名入口怎么找不被坑

广州黄埔电工证哪里考?官方报名入口怎么找不被坑 你是不是也这样,手里攥着电工证,却不知道在广州黄埔哪里能考?网上一搜一堆机构,价格五花八门,怕是被中介套路了?别急,我来给你理清楚,广州黄埔电工证到底怎么考,官方报名入口怎么找,还有怎么避坑。…

📰

福建电工证在哪查询电子证书查询

工地太忙根本没时间复习考试?福建电工证在哪考一目了然 工地太忙根本没时间复习考试,很多人想考电工证却不知道从哪下手,更别说福建电工证在哪考了。现在市面上培训机构五花八门,信息真假难辨,搞不好钱花了证还没拿到,还耽误工期。这篇文章就从…

📰

安顺电工证办理怎么考?考前押题+实操攻略全解析

安顺电工证办理怎么考?考前押题+实操攻略全解析 证书过期了不知道怎么复审延期?别慌,今天咱们就从【安顺电工证办理】说起,讲讲怎么在规定时间内完成复审,避免被处罚。特别是像你这样已经在一线干活、证书快到期的电工, 考前押题…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬