游戏中比较常用的一个效果就是背景无缝持续滚动, 以前材质系统不完善的时候,想要实现此效果, 只能是通过移动背景节点的坐标进行移动,同时还要处理好拼接的时机.
现在完全可以用Shader 进行重构实现了.
话不多说, 直接放代码:
- 材质代码:()
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
alphaThreshold: { value: 0.5 }
time: {value: 0.0 }
speed: {value: 1.0 } // time 和speed 共同决定采样的偏移量.
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
in vec3 a_position;
in vec4 a_color;
out vec4 v_color;
#if USE_TEXTURE
in vec2 a_uv0;
out vec2 v_uv0;
#endif
void main () {
vec4 pos = vec4(a_position, 1);
#if CC_USE_MODEL
pos = cc_matViewProj * cc_matWorld * pos;
#else
pos = cc_matViewProj * pos;
#endif
#if USE_TEXTURE
v_uv0 = a_uv0;
#endif
v_color = a_color;
gl_Position = pos;
}
}%
CCProgram fs %{
precision highp float;
#include <alpha-test>
in vec4 v_color;
#if USE_TEXTURE
in vec2 v_uv0;
uniform sampler2D texture;
#endif
uniform Param {
float time;
float speed;
};
void main () {
vec4 o = vec4(1, 1, 1, 1);
float offset = fract( time* speed + v_uv0.x);
o *= texture(texture, vec2(offset, v_uv0.y));
o *= v_color;
ALPHA_TEST(o);
gl_FragColor = o;
}
}%
-
通用材质球文件:(省略)
-
材质属性操控组件:
const { ccclass, property } = cc._decorator;
@ccclass("shareParam")
export class ShaderParameter {
@property()
public key: string = "";
@property()
public value: string = "";
}
@ccclass
export default class ShaderParamComponent extends cc.Component {
private sprite: cc.Sprite = null;
private _material: cc.Material = null;
private _start = 0;
@property({ type: [ShaderParameter], displayName: "参数列表", tooltip: "向材质传递自定义参数,参数类型会进行json转换." })
private params: ShaderParameter[] = [];
@property({ displayName: "更新时间", tooltip: "是否传递时间变化" })
private timeUpdate: boolean = true;
onLoad() {
this.sprite = this.getComponent(cc.Sprite);
if (this.sprite) {
this._material = this.sprite.getMaterial(0);
}
this.initParams()
}
public updateParam(key: string, value: any) {
if (!key || key.length <= 0 || typeof value === 'undefined') {
cc.warn("设置材质参数为空:", key, value)
return;
}
// 防止中途有材质变更.
if (this.sprite) {
this._material = this.sprite.getMaterial(0);
}
if (this.sprite && this._material) {
if (this._material.getProperty(key, 0) != undefined) {
this._material.setProperty(key, JSON.parse(value))
}
}
}
private initParams() {
if (this.sprite && this._material && this.params) {
for (let p of this.params) {
let key = p.key;
let value = p.value;
if (!key || key.length <= 0 || typeof value === 'undefined') {
cc.warn("设置材质参数为空:", key, value)
return;
}
if (this._material.getProperty(key, 0) != undefined) {
this._material.setProperty(key, JSON.parse(value))
}
}
}
}
protected update(dt) {
if (this.sprite) {
this._material = this.sprite.getMaterial(0);
}
if (this.node.active && this._material) {
if (this._material.getProperty("time", 0) != undefined) {
this._setShaderTime(dt);
}
}
}
private _setShaderTime(dt) {
this._material.setProperty('time', this._start);
this._start += dt;
}
}
使用方法:
在要移动的背景节点上选择此材质, 并挂载操作组件.
参数设置如下:
其中 参数speed 用于设置背景的移动速度. 可通过代码动态修改参数值.
不同的背景节点 设置不同的speed 参数, 即可实现背景视觉差 式的移动效果. 完全不需要再控制背景节点进行坐标移动.