cocos shader 让扫光特效有立体效果 deepseek生成 cocos shader
在这里插入图片描述](https://i-blog.csdnimg.cn/direct/4f6efb2189904555adccfb8d596a2a0b.gif#pic_center。



用deepseek生成的
首先得有个能运行的shader作为模版
这是提示词
// Effect Syntax Guide: https://docs.cocos.com/creator/manual/zh/shader/index.html
// Copyright © 2017-2020 Xiamen Yaji Software Co., Ltd.
// Copyright © 2017-2020 Xiamen Yaji Software Co., Ltd.
// Copyright © 2017-2020 Xiamen Yaji Software Co., Ltd.
// Copyright © 2017-2020 Xiamen Yaji Software Co., Ltd.
// Effect Syntax Guide: https://docs.cocos.com/creator/manual/zh/shader/index.html
// Copyright © 2017-2020 Xiamen Yaji Software Co., Ltd.
// Effect Syntax Guide: https://docs.cocos.com/creator/manual/zh/shader/index.html
// Copyright © 2017-2020 Xiamen Yaji Software Co., Ltd.
// 最简兼容版光柱Shader
/** glow-simple.effect **/
CCEffect %{
techniques:
- name: glow
passes:- vert: vs:vert
frag: fs:frag
blendState:
targets:- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
depthStencilState:
depthTest: false
depthWrite: false
rasterizerState:
cullMode: none
properties:
glowColor: { value: [1.0, 0.8, 0.3, 1.0], editor: { type: color } }
moveSpeed: { value: 1.0, editor: { range: [0.1, 5.0, 0.1] } }
beamWidth: { value: 0.1, editor: { range: [0.01, 0.5, 0.01] } }
curveIntensity: { value: 0.2, editor: { range: [0.0, 1.0, 0.01] } }
noiseTexture: { value: white, editor: { type: texture } }
noiseScale: { value: 5.0, editor: { range: [0.1, 20.0, 0.1] } }
noiseSpeed: { value: 0.5, editor: { range: [0.0, 2.0, 0.01] } }
hexSize: { value: 0.8, editor: { range: [0.2, 1.0, 0.01] } }
hexFeather: { value: 0.05, editor: { range: [0.0, 0.3, 0.01] } }
}%
- blend: true
- vert: vs:vert
CCProgram vs %{
precision highp float;
#include
#if USE_LOCAL
#include <builtin/uniforms/cc-local>
#endif
in vec3 a_position;
in vec2 a_texCoord;
out vec2 uv;
#if USE_LOCAL
in vec4 a_color;
out vec4 v_color;
#endif
vec4 vert() {
vec4 pos = vec4(a_position, 1);
#if USE_LOCAL
pos = cc_matWorld * pos;
v_color = a_color;
#endif
pos = cc_matViewProj * pos;
uv = a_texCoord;
return pos;
}
}%
CCProgram fs %{
precision highp float;
#include
#include
in vec2 uv;
uniform sampler2D noiseTexture;
uniform UBO {
vec4 glowColor;
float moveSpeed;
float beamWidth;
float curveIntensity;
float noiseScale;
float noiseSpeed;
float hexSize;
float hexFeather;
};
float hexDistance(vec2 p) {
vec2 q = abs§;
float d1 = q.x * 0.866075 + q.y * 0.5;
return max(d1, q.y) - 0.5;
}
vec4 frag() {
vec4 o = texture(cc_spriteTexture, uv);
vec4 original = o;
vec2 p = (uv - 0.5) / hexSize;
float d = hexDistance(p);
float mask = 1.0 - smoothstep(0.0, hexFeather, d);
if(original.a > 0.0) {
o.a = original.a * mask;
}
return o;
}
}%
这是cocos shader 请你让让光效按照原图的纹理进行流动,原理就是获取原图的明暗,原图亮的地方让光效向某个方向偏移,暗的地方向反方向偏移
**
请解释下原理 啥叫亮的推动 为啥现在有立体的效果了
**
我们需要解释“亮的地方让光效向某个方向偏移”的原理,以及为什么这样会产生立体感。
首先,回顾用户最初的需求:“让光效按照原图的明暗,原图亮的地方让光效向某个方向偏移,暗的地方向反方向偏移”。在两个 shader 中,我们实现的方式都是:
提取原图像素的亮度(luminance),常用公式 dot(rgb, vec3(0.299, 0.587, 0.114))。
计算一个偏移量 (lum - 0.5) * 强度因子。这意味着当亮度大于0.5时,偏移为正;小于0.5时,偏移为负。
将这个偏移量加到用于生成光效的坐标上。在第一个 shader 中,光效是沿 x 方向移动的光束,偏移加在 uv.x 上(phase = uv.x + brightnessOffset + time * moveSpeed);在第二个 shader 中,彩色光栅的输入相位是 (uv.x + brightnessOffset) * rasterScale + …。
这样做的结果是:原本均匀流动的光束或条纹,在遇到图像中较亮的区域时,会表现出提前到达(因为偏移为正,相当于该点的光束相位更大,也就是光束来得更早);在较暗的区域,光束会滞后。这就在视觉上扭曲了光效的直线形状,让它跟随底下图像的明暗变化而“弯曲”。
现在解释为什么会有立体效果:
人脑通过阴影、高光等明暗信息感知物体的三维形状。一张卡牌或图像上的角色、物体本身已经通过光影表现出了立体感(比如角色的亮面、暗面、高光)。
当一束光或条纹扫过这个平面图像时,如果光的形状随着图像的明暗发生相应的弯曲,就会产生一种错觉:这束光不是照在一个平面上,而是照在一个有高低起伏的表面上。即,亮的地方像是突出来的,把光束“推”向前(提早到达),暗的地方像是凹进去的,把光束“拉”向后(延迟)。这符合光学中光线在凸起表面会提前到达,在凹陷处会延迟的直觉。
这种现象类似于法线贴图或视差映射的原理,但实际上我们只是对屏幕坐标进行了一个简单的亮度驱动的扰动。由于图像本身已经包含了立体信息(亮暗),扰动光效使得光效与这个立体信息同步,加强了立体感。可能还因为彩色光栅和扫描线本身具有色散效果,更增强了金属或全息贴纸般的质感。
需要注意的是,偏移的方向选择也很重要:我们选择沿光效流动方向(多为水平方向)偏移,这样流动感仍然保持。如果改为垂直方向,效果会不同。目前这种沿流动方向的偏移能最大化地暗示表面的凹凸。
回答时应该用通俗的语言解释,避免过于技术化,但又要阐明原理。可以向用户说明:
亮度提取:得到每个像素的明暗程度。
偏移映射:亮处加正偏移(向右推),暗处加负偏移(向左拉)。
光效变形:光束相位被扭曲,不再是平行直线,而是随着纹理起伏。
立体感来源:图像本身的明暗已经暗示了立体形状,光效的扭曲与之一致,大脑就会认为光是在一个起伏的表面上滑过。
还要强调这本质上是一种视觉错觉,但效果强烈。可以比喻为“光在凹凸不平的金属表面流动”。
因此,我的回答结构可以如下:
简要概述所做的事情。
分步解释原理:亮度提取 -> 偏移计算 -> 作用到光效坐标。
解释为什么产生立体感:与图像已有的立体信息匹配,欺骗大脑。
可能补充提及 shader 中具体的代码行位置。
我将以亲切易懂的语气回答,并确保没有代码片段(除非用户要求)。
这个效果的核心原理其实很简单:我们让扫过的光线“读”懂了底下图像的明暗,并跟着这些明暗起伏变形。亮的地方让光“跑得快一点”提前到达,暗的地方让光“走慢一点”滞后出现,于是原本平平直直的光束(或彩色条纹)就变得弯弯扭扭,仿佛贴在了一个有凹凸的表面上。
下面拆开讲一下到底是怎么做到的,以及你为什么看到了立体感。
- 先给图像“测个光”
在 shader 里,我们做的第一件事就是计算出当前这个像素到底有多亮:
text
float lum = dot(original.rgb, vec3(0.299, 0.587, 0.114));
这行代码用了一个心理学亮度公式,把人眼对红绿蓝不同敏感度的权重乘进去,得到一个 0~1 的亮度值 lum。
越接近 1 就越亮(比如高光、白色区域),越接近 0 就越暗(比如黑色阴影)。
- 把亮度变成“推拉”的偏移量
接着,我们把亮度映射成一个位置偏移:
text
float brightnessOffset = (lum - 0.5) * 强度因子;
当 lum > 0.5(偏亮),brightnessOffset 为正——向正方向(右)推。
当 lum < 0.5(偏暗),brightnessOffset 为负——向反方向(左)拉。
如果亮度刚好是中间灰 0.5,偏移为 0,光不动。
这个“强度因子”通常就是你面板上的 rasterStrength 或 curveIntensity,控制扭曲的剧烈程度。
- 把偏移“喂”给流动的光
最关键的一步在这里。
原本光效(光束或彩虹条纹)是用一个随着时间和坐标变化的函数生成的,比如:
text
float rasterValue = uv.x * rasterScale + uv.y * 0.618 + time;
现在我们把亮度偏移加到空间坐标上:
text
float rasterValue = (uv.x + brightnessOffset) * rasterScale + uv.y * 0.618 + time;
这会带来什么结果呢?
对一个亮像素,brightnessOffset 是正的,就相当于把这个像素的光效“相位”往前拨了——本来应该等到下一毫秒才扫到这里的彩虹条纹,现在提前出现了。视觉上就是条纹在这个地方向右凸起、向前推移。
对一个暗像素,偏移为负,相位被推后——条纹来得更晚,看起来就像向左凹陷、落后了。
于是,原本笔直的光束/条纹,就变得像被底下的图像捏过一样,随着图像的明暗起伏而扭曲。
- 为什么这样就会有立体感?
因为你的原始图像本身就已经包含了立体信息:角色脸上的高光、衣服的褶皱阴影、金属边框的反光……这些明暗关系本来就是大脑用来判断“哪里凸、哪里凹”的线索。
现在,我们又加了一条“会读明暗”的光。
光在凸起的高亮部分加速向前冲,在凹陷的暗部减速落后,恰好模拟了光线射到真实凹凸表面时的行为——在真·3D 表面,凸起的地方光线会先到达,凹陷的地方光线会后到达。
大脑接收到这两个完全一致的信号:
图像自己的明暗 →
光效随之同步的扭曲 →
就会自动把它们“融合”,产生一种强烈错觉:哦,这束光不是照在一张平平的卡片上,而是照在一个有高低起伏的立体表面上。
所以你会感觉卡面好像变立体了,光好像真的在沿着角色、边框的轮廓“流淌”,特别有物理质感。如果配合彩虹色衍射和扫描线,甚至会有全息贴纸、烫金工艺那种实体凹凸的观感。
一句话总结:
我们用原始图像的亮度作为“地形高度”,让扫过的光束顺着这个地形上下起伏,你的眼睛就把这当成真的立体凹凸了。
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
// Effect Syntax Guide: https://docs.cocos.com/creator/manual/zh/shader/index.html
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
// Effect Syntax Guide: https://docs.cocos.com/creator/manual/zh/shader/index.html
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
// 最简兼容版光柱Shader
/** glow-simple.effect **/
CCEffect %{
techniques:
- name: glow
passes:
- vert: vs:vert
frag: fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
depthStencilState:
depthTest: false
depthWrite: false
rasterizerState:
cullMode: none
properties:
glowColor: { value: [1.0, 0.8, 0.3, 1.0], editor: { type: color } }
moveSpeed: { value: 1.0, editor: { range: [0.1, 5.0, 0.1] } }
beamWidth: { value: 0.1, editor: { range: [0.01, 0.5, 0.01] } }
curveIntensity: { value: 0.2, editor: { range: [0.0, 1.0, 0.01] } }
noiseTexture: { value: white, editor: { type: texture } }
noiseScale: { value: 5.0, editor: { range: [0.1, 20.0, 0.1] } }
noiseSpeed: { value: 0.5, editor: { range: [0.0, 2.0, 0.01] } }
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#if USE_LOCAL
#include <builtin/uniforms/cc-local>
#endif
in vec3 a_position;
in vec2 a_texCoord;
out vec2 uv;
#if USE_LOCAL
in vec4 a_color;
out vec4 v_color;
#endif
vec4 vert() {
vec4 pos = vec4(a_position, 1);
#if USE_LOCAL
pos = cc_matWorld * pos;
v_color = a_color;
#endif
pos = cc_matViewProj * pos;
uv = a_texCoord;
return pos;
}
}%
CCProgram fs %{
precision highp float;
#include <sprite-texture>
#include <cc-global>
in vec2 uv;
#if USE_LOCAL
in vec4 v_color;
#endif
uniform sampler2D noiseTexture;
uniform UBO {
vec4 glowColor;
float moveSpeed;
float beamWidth;
float curveIntensity;
float noiseScale;
float noiseSpeed;
};
vec4 frag() {
vec4 o = texture(cc_spriteTexture, uv);
vec4 original = o;
if (original.a < 0.05) discard;
// 1. 提取原图亮度
float lum = dot(original.rgb, vec3(0.299, 0.587, 0.114));
// 2. 亮度驱动 x 方向偏移:亮处为正(向右),暗处为负(向左)
float brightnessOffset = (lum - 0.5) * curveIntensity * 2.0;
// 3. 光束基础移动位置(时间驱动)
float time = cc_time.x * moveSpeed;
float beamPosX = mod(time, 1.5) - 0.25;
// 4. y 方向沿用噪声偏移
vec2 noiseUV = vec2(beamPosX * noiseScale, cc_time.x * noiseSpeed);
float noiseVal = texture(noiseTexture, noiseUV).r;
float curveOffset = (noiseVal - 0.5) * 2.0 * curveIntensity;
float beamPosY = 0.5 ;
// 5. 关键:计算当前像素到光点的距离时,x 坐标加上亮度偏移
float dist = distance(vec2(uv.x + brightnessOffset, uv.y),
vec2(beamPosX, beamPosY));
// 6. 如果像素在光束范围内,叠加光效
if (dist < beamWidth) {
float strength = 1.0 - dist / beamWidth;
vec3 glowEffect = mix(vec3(1.0), glowColor.rgb, dist / beamWidth);
o.rgb = original.rgb + glowEffect * strength;
o.a = max(original.a, strength);
}
return o;
}
}%
更多推荐



所有评论(0)