I have written a custom shader program that I would like to apply on my node to distort the sprite attached on my node.
I called the line below to set the program on the node in the script attached to the node: node.setShaderProgram(customProgram);
This works, and when I play the project on the Browser I can see my shader program activated on the node. But in the Cocos Creator editor it still shows the normal undistorted sprite. How do I get the editor to redraw the node with the shader applied on it? What if I need to animate the shader effect on the editor with a variable passed in from the node’s property?
I see this in the Creator code: _sgNode._renderCmd.setDirtyFlag(_ccsg.Node._dirtyFlags.contentDirty);
but am not sure how to use it to trigger a redraw on the editor. Can anybody please help?
To make the editor redraw and animate the shader, you would have to define a set() method for your property, and in that set method you will need to call your shader program and update it with the current value.
Example for my property:
properties: {
_strength: 1.0,
strength: {
get: function () {
return this._strength;
},
set: function (value) {
this._strength = parseFloat(value);
this.setShader();
if(this._program) { // the shader is set
this._program.use();
this._program.setUniformLocationWith1f( this._strengthLoc, this._strength );
}
},
type: cc.Float,
animatable: true,
displayName: 'Distortion Strength',
},
},
No need for any setDirty! Hope this helps someone.
You could also use notify for efficiency sake. I found this method by reading the engine codes. Here’s a snip from cc.Label:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return CC_JSB ? function (...args) {
var context = this;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
} : function () {
var context = this;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, arguments);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, arguments);
};
}
properties: {
_useOriginalSize: true,
/**
* !#en Content string of label.
* !#zh 标签显示的文本内容。
* @property {String} string
*/
string: {
default: 'Label',
multiline: true,
tooltip: CC_DEV && 'i18n:COMPONENT.label.string',
notify: function () {
if (this._sgNode) {
if (CC_EDITOR) {
if (this.overflow === cc.Label.Overflow.SHRINK) {
this.fontSize = this._userDefinedFontSize;
}
this._debouncedUpdateSgNodeString();
} else {
this._updateSgNodeString();
}
}
}
},