更新一个Shader特效,使图片纹理产生流光和闪光效果

This commit is contained in:
leo
2018-05-29 19:43:55 +08:00
parent 7b6730b527
commit acd1bbca07
25 changed files with 21615 additions and 0 deletions

67
FluxayShader/.gitignore vendored Normal file
View File

@@ -0,0 +1,67 @@
#/////////////////////////////////////////////////////////////////////////////
# Fireball Projects
#/////////////////////////////////////////////////////////////////////////////
library/
temp/
local/
build/
#/////////////////////////////////////////////////////////////////////////////
# Logs and databases
#/////////////////////////////////////////////////////////////////////////////
*.log
*.sql
*.sqlite
#/////////////////////////////////////////////////////////////////////////////
# files for debugger
#/////////////////////////////////////////////////////////////////////////////
*.sln
*.csproj
*.pidb
*.unityproj
*.suo
#/////////////////////////////////////////////////////////////////////////////
# OS generated files
#/////////////////////////////////////////////////////////////////////////////
.DS_Store
ehthumbs.db
Thumbs.db
#/////////////////////////////////////////////////////////////////////////////
# exvim files
#/////////////////////////////////////////////////////////////////////////////
*UnityVS.meta
*.err
*.err.meta
*.exvim
*.exvim.meta
*.vimentry
*.vimentry.meta
*.vimproject
*.vimproject.meta
.vimfiles.*/
.exvim.*/
quick_gen_project_*_autogen.bat
quick_gen_project_*_autogen.bat.meta
quick_gen_project_*_autogen.sh
quick_gen_project_*_autogen.sh.meta
.exvim.app
#/////////////////////////////////////////////////////////////////////////////
# webstorm files
#/////////////////////////////////////////////////////////////////////////////
.idea/
#//////////////////////////
# VS Code
#//////////////////////////
.vscode/

2
FluxayShader/README.md Normal file
View File

@@ -0,0 +1,2 @@
# 流动闪光特效
使图片纹理产生流光和闪光效果

View File

@@ -0,0 +1,6 @@
{
"ver": "1.0.1",
"uuid": "29f52784-2fca-467b-92e7-8fd9ef8c57b7",
"isGroup": false,
"subMetas": {}
}

View File

@@ -0,0 +1,498 @@
[
{
"__type__": "cc.SceneAsset",
"_name": "",
"_objFlags": 0,
"_rawFiles": null,
"scene": {
"__id__": 1
}
},
{
"__type__": "cc.Scene",
"_objFlags": 0,
"_parent": null,
"_children": [
{
"__id__": 2
}
],
"_tag": -1,
"_active": true,
"_components": [],
"_prefab": null,
"_id": "2d2f792f-a40c-49bb-a189-ed176a246e49",
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_cascadeOpacityEnabled": true,
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_contentSize": {
"__type__": "cc.Size",
"width": 0,
"height": 0
},
"_localZOrder": 0,
"_globalZOrder": 0,
"_opacityModifyRGB": false,
"groupIndex": 0,
"autoReleaseAssets": false
},
{
"__type__": "cc.Node",
"_name": "Canvas",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [
{
"__id__": 3
},
{
"__id__": 6
},
{
"__id__": 11
}
],
"_tag": -1,
"_active": true,
"_components": [
{
"__id__": 13
},
{
"__id__": 14
}
],
"_prefab": null,
"_id": "a286bbGknJLZpRpxROV6M94",
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 252,
"g": 252,
"b": 252,
"a": 255
},
"_cascadeOpacityEnabled": true,
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_contentSize": {
"__type__": "cc.Size",
"width": 960,
"height": 640
},
"_rotationX": 0,
"_rotationY": 0,
"_scaleX": 1,
"_scaleY": 1,
"_position": {
"__type__": "cc.Vec2",
"x": 480,
"y": 320
},
"_skewX": 0,
"_skewY": 0,
"_localZOrder": 0,
"_globalZOrder": 0,
"_opacityModifyRGB": false,
"groupIndex": 0
},
{
"__type__": "cc.Node",
"_name": "background",
"_objFlags": 0,
"_parent": {
"__id__": 2
},
"_children": [],
"_tag": -1,
"_active": true,
"_components": [
{
"__id__": 4
},
{
"__id__": 5
}
],
"_prefab": null,
"_id": "e2e0crkOLxGrpMxpbC4iQg1",
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 27,
"g": 38,
"b": 46,
"a": 255
},
"_cascadeOpacityEnabled": true,
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_contentSize": {
"__type__": "cc.Size",
"width": 960,
"height": 640
},
"_rotationX": 0,
"_rotationY": 0,
"_scaleX": 1,
"_scaleY": 1,
"_position": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_skewX": 0,
"_skewY": 0,
"_localZOrder": 0,
"_globalZOrder": 0,
"_opacityModifyRGB": false,
"groupIndex": 0
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
},
"_enabled": true,
"isAlignOnce": true,
"_target": null,
"_alignFlags": 45,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 200,
"_originalHeight": 150
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
},
"_enabled": true,
"_spriteFrame": {
"__uuid__": "410fb916-8721-4663-bab8-34397391ace7"
},
"_type": 1,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_atlas": null
},
{
"__type__": "cc.Node",
"_name": "cocos",
"_objFlags": 0,
"_parent": {
"__id__": 2
},
"_children": [
{
"__id__": 7
}
],
"_tag": -1,
"_active": true,
"_components": [
{
"__id__": 9
},
{
"__id__": 10
}
],
"_prefab": null,
"_id": "c4f30YOS65G64U2TwufdJ+2",
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_cascadeOpacityEnabled": true,
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_contentSize": {
"__type__": "cc.Size",
"width": 195,
"height": 270
},
"_rotationX": 0,
"_rotationY": 0,
"_scaleX": 1,
"_scaleY": 1,
"_position": {
"__type__": "cc.Vec2",
"x": 0,
"y": 50
},
"_skewX": 0,
"_skewY": 0,
"_localZOrder": 0,
"_globalZOrder": 0,
"_opacityModifyRGB": false,
"groupIndex": 0
},
{
"__type__": "cc.Node",
"_name": "New Label",
"_objFlags": 0,
"_parent": {
"__id__": 6
},
"_children": [],
"_tag": -1,
"_active": true,
"_components": [
{
"__id__": 8
}
],
"_prefab": null,
"_id": "87AruQhzhOfbxec4C5Kfvs",
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_cascadeOpacityEnabled": true,
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_contentSize": {
"__type__": "cc.Size",
"width": 98,
"height": 40
},
"_rotationX": 0,
"_rotationY": 0,
"_scaleX": 1,
"_scaleY": 1,
"_position": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_skewX": 0,
"_skewY": 0,
"_localZOrder": 0,
"_globalZOrder": 0,
"_opacityModifyRGB": false,
"groupIndex": 0
},
{
"__type__": "cc.Label",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 7
},
"_enabled": true,
"_useOriginalSize": false,
"_actualFontSize": 40,
"_fontSize": 40,
"_lineHeight": 40,
"_enableWrapText": true,
"_N$file": null,
"_isSystemFontUsed": true,
"_spacingX": 0,
"_N$string": "Label",
"_N$horizontalAlign": 1,
"_N$verticalAlign": 1,
"_N$fontFamily": "Arial",
"_N$overflow": 0
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 6
},
"_enabled": true,
"_spriteFrame": {
"__uuid__": "31bc895a-c003-4566-a9f3-2e54ae1c17dc"
},
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_atlas": null
},
{
"__type__": "20987EwW8FJZ7peyE/Wj0WX",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 6
},
"_enabled": true,
"mode": 1,
"_fragStr": null,
"_program": null,
"_startTime": 1526032675120,
"_time": 0
},
{
"__type__": "cc.Node",
"_name": "label",
"_objFlags": 0,
"_parent": {
"__id__": 2
},
"_children": [],
"_tag": -1,
"_active": true,
"_components": [
{
"__id__": 12
}
],
"_prefab": null,
"_id": "31f1bH7V69Ajr1iXhluMpTB",
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_cascadeOpacityEnabled": true,
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_contentSize": {
"__type__": "cc.Size",
"width": 147,
"height": 60
},
"_rotationX": 0,
"_rotationY": 0,
"_scaleX": 1,
"_scaleY": 1,
"_position": {
"__type__": "cc.Vec2",
"x": 0,
"y": -180
},
"_skewX": 0,
"_skewY": 0,
"_localZOrder": 0,
"_globalZOrder": 0,
"_opacityModifyRGB": false,
"groupIndex": 0
},
{
"__type__": "cc.Label",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 11
},
"_enabled": true,
"_useOriginalSize": false,
"_actualFontSize": 40,
"_fontSize": 60,
"_lineHeight": 60,
"_enableWrapText": true,
"_N$file": null,
"_isSystemFontUsed": true,
"_spacingX": 0,
"_N$string": "Label",
"_N$horizontalAlign": 1,
"_N$verticalAlign": 1,
"_N$fontFamily": "Arial",
"_N$overflow": 0
},
{
"__type__": "cc.Canvas",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
},
"_enabled": true,
"_designResolution": {
"__type__": "cc.Size",
"width": 960,
"height": 640
},
"_fitWidth": false,
"_fitHeight": true
},
{
"__type__": "280c3rsZJJKnZ9RqbALVwtK",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
},
"_enabled": true,
"label": {
"__id__": 12
},
"text": "Hello, World!"
}
]

View File

@@ -0,0 +1,7 @@
{
"ver": "1.0.0",
"uuid": "2d2f792f-a40c-49bb-a189-ed176a246e49",
"asyncLoadAssets": false,
"autoReleaseAssets": false,
"subMetas": {}
}

View File

@@ -0,0 +1,6 @@
{
"ver": "1.0.1",
"uuid": "4734c20c-0db8-4eb2-92ea-e692f4d70934",
"isGroup": false,
"subMetas": {}
}

View File

@@ -0,0 +1,71 @@
const Fluxay = require('FluxayFrag');
cc.Class({
extends: cc.Component,
properties: {
mode: 0,
_fragStr: null,
_program: null,
_startTime: Date.now(),
_time: 0,
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
this._startTime= Date.now();
if (this.mode == 0) {
this._fragStr = Fluxay.fluxay_frag;
} else {
this._fragStr = Fluxay.fluxay_frag_super;
}
this.userWater();
},
userWater() {
this._program = new cc.GLProgram();
if (cc.sys.isNative) {
this._program.initWithString(Fluxay.fluxay_vert, this._fragStr);
} else {
this._program.initWithVertexShaderByteArray(Fluxay.fluxay_vert, this._fragStr);
this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_POSITION, cc.macro.VERTEX_ATTRIB_POSITION);
this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_COLOR, cc.macro.VERTEX_ATTRIB_COLOR);
this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_TEX_COORD, cc.macro.VERTEX_ATTRIB_TEX_COORDS);
}
this._program.link();
this._program.updateUniforms();
this._program.use();
if (cc.sys.isNative) {
var glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(this._program);
glProgram_state.setUniformFloat("time", this._time);
} else {
let ba = this._program.getUniformLocationForName("time");
this._program.setUniformLocationWith1f(ba, this.time);
}
this.setProgram(this.node.getComponent(cc.Sprite)._sgNode, this._program);
},
setProgram(node, program) {
if (cc.sys.isNative) {
var glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(program);
node.setGLProgramState(glProgram_state);
} else {
node.setShaderProgram(program);
}
},
update(dt) {
this._time = (Date.now() - this._startTime) / 1000;
if (this._program) {
this._program.use();
if (cc.sys.isNative) {
var glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(this._program);
glProgram_state.setUniformFloat("time", this._time);
} else {
let ct = this._program.getUniformLocationForName("time");
this._program.setUniformLocationWith1f(ct, this._time);
}
}
}
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "20987130-5bc1-4967-ba5e-c84fd68f4597",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,136 @@
// Feofox Game
// Author:Lerry
// https://github.com/fylz1125/ShaderDemos
let fluxay_vert = `
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
varying vec2 v_texCoord;
varying vec4 v_fragmentColor;
void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
`;
// 流光特效
let fluxay_frag = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform float time;
void main()
{
vec4 src_color = texture2D(CC_Texture0, v_texCoord).rgba;
float width = 0.22; //流光的宽度范围 (调整该值改变流光的宽度)
float start = tan(time/1.414); //流光的起始x坐标
float strength = 0.006; //流光增亮强度 (调整该值改变流光的增亮强度)
float offset = 0.5; //偏移值 (调整该值改变流光的倾斜程度)
if( v_texCoord.x < (start - offset * v_texCoord.y) && v_texCoord.x > (start - offset * v_texCoord.y - width))
{
vec3 improve = strength * vec3(255, 255, 255);
vec3 result = improve * vec3( src_color.r, src_color.g, src_color.b);
gl_FragColor = vec4(result, src_color.a);
}else{
gl_FragColor = src_color;
}
}
`;
// 流光的另一种写法
let fluxay_frag_s = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
// uniform float factor;
// uniform float width;
uniform float time;
// uniform vec3 color;
void main()
{
float factor = .06;
float width = .02;
// float offset = .5;
vec3 color = vec3(10.,10.,10.);
vec4 texColor = texture2D(CC_Texture0, v_texCoord);
float distance = abs(v_texCoord[0]+v_texCoord[1]-tan(time))/1.414;
distance = 1.0-(1.0/width)*distance;
distance = max(distance, 0.0);
vec4 sample = vec4(0.0,0.0,0.0,0.0);
sample[0] = color[0] * distance;
sample[1] = color[1] * distance;
sample[2] = color[2] * distance;
sample[3] = distance;
float alpha = sample[3]*texColor[3];
texColor[0] = texColor[0] + sample[0]*alpha*factor;
texColor[1] = texColor[1] + sample[1]*alpha*factor;
texColor[2] = texColor[2] + sample[2]*alpha*factor;
gl_FragColor = v_fragmentColor * texColor;
}
`;
// 波光特效
let fluxay_frag_super = `
#define TAU 6.120470874064187
#define MAX_ITER 5
uniform float time;
varying vec2 v_texCoord;
varying vec4 v_fragmentColor;
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float time = time * .5+5.;
// uv should be the 0-1 uv of texture...
vec2 uv = v_texCoord.xy;//fragCoord.xy / iResolution.xy;
vec2 p = mod(uv*TAU, TAU)-250.0;
vec2 i = vec2(p);
float c = 1.0;
float inten = .0045;
for (int n = 0; n < MAX_ITER; n++)
{
float t = time * (1.0 - (3.5 / float(n+1)));
i = p + vec2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(1.5*t + i.x));
c += 1.0/length(vec2(p.x / (cos(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));
}
c /= float(MAX_ITER);
c = 1.17-pow(c, 1.4);
vec4 tex = texture2D(CC_Texture0,uv);
vec3 colour = vec3(pow(abs(c), 20.0));
colour = clamp(colour + vec3(0.0, 0.0, .0), 0.0, tex.a);
// 混合波光
float alpha = c*tex[3];
tex[0] = tex[0] + colour[0]*alpha;
tex[1] = tex[1] + colour[1]*alpha;
tex[2] = tex[2] + colour[2]*alpha;
fragColor = v_fragmentColor * tex;
}
void main()
{
mainImage(gl_FragColor, gl_FragCoord.xy);
}
`;
module.exports = {
fluxay_vert: fluxay_vert,
fluxay_frag: fluxay_frag,
fluxay_frag_s: fluxay_frag_s,
fluxay_frag_super: fluxay_frag_super
};

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "7ed09699-8c92-49c0-a73a-d01936616876",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,22 @@
cc.Class({
extends: cc.Component,
properties: {
label: {
default: null,
type: cc.Label
},
// defaults, set visually when attaching this script to the Canvas
text: 'Hello, World!'
},
// use this for initialization
onLoad: function () {
this.label.string = this.text;
},
// called every frame
update: function (dt) {
},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "280c3aec-6492-4a9d-9f51-a9b00b570b4a",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -0,0 +1,6 @@
{
"ver": "1.0.1",
"uuid": "7b81d4e8-ec84-4716-968d-500ac1d78a54",
"isGroup": false,
"subMetas": {}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,30 @@
{
"ver": "1.0.0",
"uuid": "6aa0aa6a-ebee-4155-a088-a687a6aadec4",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"subMetas": {
"HelloWorld": {
"ver": "1.0.3",
"uuid": "31bc895a-c003-4566-a9f3-2e54ae1c17dc",
"rawTextureUuid": "6aa0aa6a-ebee-4155-a088-a687a6aadec4",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 195,
"height": 270,
"rawWidth": 195,
"rawHeight": 270,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,30 @@
{
"ver": "1.0.0",
"uuid": "a8027877-d8d6-4645-97a0-52d4a0123dba",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"subMetas": {
"singleColor": {
"ver": "1.0.3",
"uuid": "410fb916-8721-4663-bab8-34397391ace7",
"rawTextureUuid": "a8027877-d8d6-4645-97a0-52d4a0123dba",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 2,
"height": 2,
"rawWidth": 2,
"rawHeight": 2,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

20635
FluxayShader/creator.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"experimentalDecorators": true
},
"exclude": [
"node_modules",
".vscode",
"library",
"local",
"settings",
"temp"
]
}

View File

@@ -0,0 +1,4 @@
{
"engine": "cocos2d-html5",
"packages": "packages"
}

View File

@@ -0,0 +1,13 @@
{
"excludeScenes": [],
"orientation": {
"landscapeLeft": true,
"landscapeRight": true,
"portrait": false,
"upsideDown": false
},
"packageName": "org.cocos2d.helloworld",
"startScene": "2d2f792f-a40c-49bb-a189-ed176a246e49",
"title": "hello_world",
"webOrientation": "auto"
}

View File

@@ -0,0 +1,7 @@
{
"excludeScenes": [],
"packageName": "org.cocos2d.helloworld",
"platform": "web-mobile",
"startScene": "2d2f792f-a40c-49bb-a189-ed176a246e49",
"title": "HelloWorld"
}

View File

@@ -0,0 +1,28 @@
{
"collision-matrix": [
[
true
]
],
"excluded-modules": [],
"group-list": [
"default"
],
"start-scene": "current",
"design-resolution-width": 960,
"design-resolution-height": 640,
"fit-width": false,
"fit-height": true,
"use-project-simulator-setting": false,
"simulator-orientation": false,
"use-customize-simulator": false,
"simulator-resolution": {
"width": 960,
"height": 640
},
"cocos-analytics": {
"enable": false,
"appID": "13798",
"appSecret": "959b3ac0037d0f3c2fdce94f8421a9b2"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,5 @@
{
"name": "TEMPLATES.helloworld.name",
"desc": "TEMPLATES.helloworld.desc",
"banner": "template-banner.png"
}