mirror of
https://github.com/photonstorm/phaser
synced 2024-11-27 07:01:20 +00:00
Revised FX pipeline. Added Glow, Shadow and Pixelate. Tested against multi-pass.
This commit is contained in:
parent
c09ce7b2e9
commit
532d5a9375
13 changed files with 558 additions and 168 deletions
|
@ -4,6 +4,10 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Glow = require('../fx/Glow');
|
||||
var Shadow = require('../fx/Shadow');
|
||||
var Pixelate = require('../fx/Pixelate');
|
||||
|
||||
/**
|
||||
* Provides methods used for setting the FX values of a Game Object.
|
||||
* Should be applied as a mixin and not used directly.
|
||||
|
@ -93,28 +97,8 @@ var FX = {
|
|||
{
|
||||
},
|
||||
|
||||
enableFX: function ()
|
||||
enableFX: function (padding)
|
||||
{
|
||||
this.fx = {
|
||||
glow: {
|
||||
quality: 0.1,
|
||||
distance: 10,
|
||||
outerStrength: 4,
|
||||
innerStrength: 0,
|
||||
knockout: false,
|
||||
color: [ 1, 1, 1, 1 ]
|
||||
},
|
||||
shadow: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
decay: 0.1,
|
||||
power: 1.0,
|
||||
shadowColor: [ 0, 0, 0, 1 ],
|
||||
samples: 12,
|
||||
intensity: 1
|
||||
}
|
||||
};
|
||||
|
||||
var renderer = this.scene.sys.renderer;
|
||||
|
||||
if (!renderer)
|
||||
|
@ -132,9 +116,66 @@ var FX = {
|
|||
|
||||
this.pipeline = pipeline;
|
||||
|
||||
if (!this.fx)
|
||||
{
|
||||
this.fx = [];
|
||||
}
|
||||
|
||||
if (padding !== undefined)
|
||||
{
|
||||
this.fxPadding = padding;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
clearFX: function ()
|
||||
{
|
||||
// Remove them all
|
||||
},
|
||||
|
||||
removeFX: function (fx)
|
||||
{
|
||||
// Remove specific fx
|
||||
},
|
||||
|
||||
disableFX: function (clear)
|
||||
{
|
||||
this.resetPipeline();
|
||||
|
||||
if (clear)
|
||||
{
|
||||
this.clearFX();
|
||||
}
|
||||
},
|
||||
|
||||
addGlowFX: function ()
|
||||
{
|
||||
var fx = new Glow(this);
|
||||
|
||||
this.fx.push(fx);
|
||||
|
||||
return fx;
|
||||
},
|
||||
|
||||
addShadowFX: function ()
|
||||
{
|
||||
var fx = new Shadow(this);
|
||||
|
||||
this.fx.push(fx);
|
||||
|
||||
return fx;
|
||||
},
|
||||
|
||||
addPixelateFX: function ()
|
||||
{
|
||||
var fx = new Pixelate(this);
|
||||
|
||||
this.fx.push(fx);
|
||||
|
||||
return fx;
|
||||
},
|
||||
|
||||
addBloom: function (r, g, b)
|
||||
{
|
||||
}
|
||||
|
|
73
src/gameobjects/fx/Glow.js
Normal file
73
src/gameobjects/fx/Glow.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2013-2023 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Class = require('../../utils/Class');
|
||||
var FX_CONST = require('./const');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
*
|
||||
* @class Glow
|
||||
* @memberof Phaser.GameObjects.FX
|
||||
* @constructor
|
||||
* @since 3.60.0
|
||||
*
|
||||
* @param {Phaser.GameObjects.GameObject} gameObject - A reference to the Game Object that has this fx.
|
||||
*/
|
||||
var Glow = new Class({
|
||||
|
||||
initialize:
|
||||
|
||||
function Glow (gameObject)
|
||||
{
|
||||
this.type = FX_CONST.GLOW;
|
||||
|
||||
this.gameObject = gameObject;
|
||||
|
||||
this.active = true;
|
||||
|
||||
this.distance = 16;
|
||||
this.outerStrength = 4;
|
||||
this.innerStrength = 0;
|
||||
this.knockout = false;
|
||||
this._color = [ 1, 1, 1, 1 ];
|
||||
},
|
||||
|
||||
/**
|
||||
* The color of the glow.
|
||||
*
|
||||
* @name Phaser.GameObjects.FX.Glow#color
|
||||
* @type {number}
|
||||
* @since 3.60.0
|
||||
*/
|
||||
color: {
|
||||
|
||||
get: function ()
|
||||
{
|
||||
var color = this._color;
|
||||
|
||||
return (((color[0] * 255) << 16) + ((color[1] * 255) << 8) + (color[2] * 255 | 0));
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
var color = this._color;
|
||||
|
||||
color[0] = ((value >> 16) & 0xFF) / 255;
|
||||
color[1] = ((value >> 8) & 0xFF) / 255;
|
||||
color[2] = (value & 0xFF) / 255;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
destroy: function ()
|
||||
{
|
||||
this.gameObject = null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = Glow;
|
42
src/gameobjects/fx/Pixelate.js
Normal file
42
src/gameobjects/fx/Pixelate.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2013-2023 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Class = require('../../utils/Class');
|
||||
var FX_CONST = require('./const');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
*
|
||||
* @class Pixelate
|
||||
* @memberof Phaser.GameObjects.FX
|
||||
* @constructor
|
||||
* @since 3.60.0
|
||||
*
|
||||
* @param {Phaser.GameObjects.GameObject} gameObject - A reference to the Game Object that has this fx.
|
||||
*/
|
||||
var Pixelate = new Class({
|
||||
|
||||
initialize:
|
||||
|
||||
function Pixelate (gameObject)
|
||||
{
|
||||
this.type = FX_CONST.PIXELATE;
|
||||
|
||||
this.gameObject = gameObject;
|
||||
|
||||
this.active = true;
|
||||
|
||||
this.amount = 1;
|
||||
},
|
||||
|
||||
destroy: function ()
|
||||
{
|
||||
this.gameObject = null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = Pixelate;
|
75
src/gameobjects/fx/Shadow.js
Normal file
75
src/gameobjects/fx/Shadow.js
Normal file
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2013-2023 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Class = require('../../utils/Class');
|
||||
var FX_CONST = require('./const');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
*
|
||||
* @class Shadow
|
||||
* @memberof Phaser.GameObjects.FX
|
||||
* @constructor
|
||||
* @since 3.60.0
|
||||
*
|
||||
* @param {Phaser.GameObjects.GameObject} gameObject - A reference to the Game Object that has this fx.
|
||||
*/
|
||||
var Shadow = new Class({
|
||||
|
||||
initialize:
|
||||
|
||||
function Shadow (gameObject)
|
||||
{
|
||||
this.type = FX_CONST.SHADOW;
|
||||
|
||||
this.gameObject = gameObject;
|
||||
|
||||
this.active = true;
|
||||
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.decay = 0.1;
|
||||
this.power = 1.0;
|
||||
this._color = [ 0, 0, 0, 1 ];
|
||||
this.samples = 6; // max 12, min 1
|
||||
this.intensity = 1;
|
||||
},
|
||||
|
||||
/**
|
||||
* The color of the shadow.
|
||||
*
|
||||
* @name Phaser.GameObjects.FX.Shadow#color
|
||||
* @type {number}
|
||||
* @since 3.60.0
|
||||
*/
|
||||
color: {
|
||||
|
||||
get: function ()
|
||||
{
|
||||
var color = this._color;
|
||||
|
||||
return (((color[0] * 255) << 16) + ((color[1] * 255) << 8) + (color[2] * 255 | 0));
|
||||
},
|
||||
|
||||
set: function (value)
|
||||
{
|
||||
var color = this._color;
|
||||
|
||||
color[0] = ((value >> 16) & 0xFF) / 255;
|
||||
color[1] = ((value >> 8) & 0xFF) / 255;
|
||||
color[2] = (value & 0xFF) / 255;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
destroy: function ()
|
||||
{
|
||||
this.gameObject = null;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = Shadow;
|
41
src/gameobjects/fx/const.js
Normal file
41
src/gameobjects/fx/const.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2013-2023 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var FX_CONST = {
|
||||
|
||||
/**
|
||||
* The Glow FX.
|
||||
*
|
||||
* @name Phaser.GameObjects.FX.GLOW
|
||||
* @type {number}
|
||||
* @const
|
||||
* @since 3.60.0
|
||||
*/
|
||||
GLOW: 4,
|
||||
|
||||
/**
|
||||
* The Shadow FX.
|
||||
*
|
||||
* @name Phaser.GameObjects.FX.SHADOW
|
||||
* @type {number}
|
||||
* @const
|
||||
* @since 3.60.0
|
||||
*/
|
||||
SHADOW: 5,
|
||||
|
||||
/**
|
||||
* The Pixelate FX.
|
||||
*
|
||||
* @name Phaser.GameObjects.FX.PIXELATE
|
||||
* @type {number}
|
||||
* @const
|
||||
* @since 3.60.0
|
||||
*/
|
||||
PIXELATE: 6
|
||||
|
||||
};
|
||||
|
||||
module.exports = FX_CONST;
|
|
@ -5,9 +5,10 @@
|
|||
*/
|
||||
|
||||
var Class = require('../../../utils/Class');
|
||||
var PreFXPipeline = require('./PreFXPipeline');
|
||||
var BloomFrag = require('../shaders/FXBloom-frag.js');
|
||||
var FX_CONST = require('../../../gameobjects/fx/const');
|
||||
var GlowFrag = require('../shaders/FXGlow-frag.js');
|
||||
var PixelateFrag = require('../shaders/FXPixelate-frag.js');
|
||||
var PreFXPipeline = require('./PreFXPipeline');
|
||||
var ShadowFrag = require('../shaders/FXShadow-frag.js');
|
||||
var SingleQuadVS = require('../shaders/Single-vert.js');
|
||||
|
||||
|
@ -30,54 +31,17 @@ var FXPipeline = new Class({
|
|||
|
||||
function FXPipeline (config)
|
||||
{
|
||||
var shaders = [];
|
||||
|
||||
var fragShader = GlowFrag;
|
||||
var quality = 0.1;
|
||||
var distance = 10;
|
||||
|
||||
fragShader = fragShader.replace(/__SIZE__/gi, `${(1 / quality / distance).toFixed(7)}`);
|
||||
fragShader = fragShader.replace(/__DIST__/gi, `${distance.toFixed(0)}.0`);
|
||||
|
||||
shaders.push({
|
||||
name: 'Glow',
|
||||
fragShader: fragShader,
|
||||
vertShader: SingleQuadVS
|
||||
});
|
||||
|
||||
fragShader = ShadowFrag;
|
||||
|
||||
var samples = 12;
|
||||
|
||||
fragShader = fragShader.replace(/__SAMPLES__/gi, samples.toFixed(0));
|
||||
|
||||
shaders.push({
|
||||
name: 'Shadow',
|
||||
fragShader: fragShader,
|
||||
vertShader: SingleQuadVS
|
||||
});
|
||||
|
||||
config.shaders = shaders;
|
||||
config.shaders = [
|
||||
{ name: 'Glow', fragShader: GlowFrag, vertShader: SingleQuadVS },
|
||||
{ name: 'Shadow', fragShader: ShadowFrag, vertShader: SingleQuadVS },
|
||||
{ name: 'Pixelate', fragShader: PixelateFrag, vertShader: SingleQuadVS }
|
||||
];
|
||||
|
||||
PreFXPipeline.call(this, config);
|
||||
|
||||
this.bloom = {
|
||||
steps: 4,
|
||||
offsetX: 2,
|
||||
offsetY: 3,
|
||||
blurStrength: 1,
|
||||
strength: 1.5,
|
||||
color: [ 1, 1, 1 ]
|
||||
};
|
||||
|
||||
this.glow = {
|
||||
quality: 0.1,
|
||||
distance: 10,
|
||||
outerStrength: 4,
|
||||
innerStrength: 0,
|
||||
knockout: false,
|
||||
color: [ 1, 1, 1, 1 ]
|
||||
};
|
||||
this.source;
|
||||
this.target;
|
||||
this.swap;
|
||||
},
|
||||
|
||||
boot: function ()
|
||||
|
@ -85,60 +49,130 @@ var FXPipeline = new Class({
|
|||
PreFXPipeline.prototype.boot.call(this);
|
||||
|
||||
console.log(this.shaders);
|
||||
|
||||
},
|
||||
|
||||
onDraw: function (target1, target2, target3)
|
||||
{
|
||||
// tempSprite = current sprite being drawn
|
||||
this.source = target1;
|
||||
this.target = target2;
|
||||
this.swap = target3;
|
||||
|
||||
this.setShader(this.shaders[4]);
|
||||
var drawn = false;
|
||||
var sprite = this.tempSprite;
|
||||
|
||||
var glow = this.tempSprite.fx.glow;
|
||||
if (sprite && sprite.fx)
|
||||
{
|
||||
for (var i = 0; i < sprite.fx.length; i++)
|
||||
{
|
||||
var fx = sprite.fx[i];
|
||||
|
||||
this.set1f('outerStrength', glow.outerStrength);
|
||||
this.set1f('innerStrength', glow.innerStrength);
|
||||
this.set4fv('glowColor', glow.color);
|
||||
this.setBoolean('knockout', glow.knockout);
|
||||
this.set2f('resolution', target1.width, target1.height);
|
||||
if (fx.active)
|
||||
{
|
||||
switch (fx.type)
|
||||
{
|
||||
case FX_CONST.GLOW:
|
||||
this.onGlowDraw(fx);
|
||||
drawn = true;
|
||||
break;
|
||||
|
||||
this.copy(target1, target2);
|
||||
case FX_CONST.SHADOW:
|
||||
this.onShadowDraw(fx);
|
||||
drawn = true;
|
||||
break;
|
||||
|
||||
this.setShader(this.shaders[5]);
|
||||
case FX_CONST.PIXELATE:
|
||||
this.onPixelateDraw(fx);
|
||||
drawn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var shadow = this.tempSprite.fx.shadow;
|
||||
if (!drawn)
|
||||
{
|
||||
this.source = target1;
|
||||
}
|
||||
|
||||
this.set1f('intensity', shadow.intensity);
|
||||
this.set1f('decay', shadow.decay);
|
||||
this.set1f('power', shadow.power / shadow.samples);
|
||||
this.set2f('lightPosition', shadow.x, shadow.y);
|
||||
this.set4fv('shadowColor', shadow.shadowColor);
|
||||
|
||||
this.copy(target2, target1);
|
||||
|
||||
this.drawToGame(target1);
|
||||
this.drawToGame(this.source);
|
||||
},
|
||||
|
||||
onBloomDraw: function (target1, target2, target3)
|
||||
onGlowDraw: function (config)
|
||||
{
|
||||
this.manager.copyFrame(target1, target3);
|
||||
var source = this.source;
|
||||
var target = this.target;
|
||||
|
||||
var x = (2 / target1.width) * this.offsetX;
|
||||
var y = (2 / target1.height) * this.offsetY;
|
||||
this.setShader(this.shaders[FX_CONST.GLOW]);
|
||||
|
||||
for (var i = 0; i < this.steps; i++)
|
||||
this.set1f('distance', config.distance);
|
||||
this.set1f('outerStrength', config.outerStrength);
|
||||
this.set1f('innerStrength', config.innerStrength);
|
||||
this.set4fv('glowColor', config._color);
|
||||
this.setBoolean('knockout', config.knockout);
|
||||
this.set2f('resolution', source.width, source.height);
|
||||
|
||||
this.copy(source, target);
|
||||
|
||||
this.source = target;
|
||||
this.target = source;
|
||||
},
|
||||
|
||||
onShadowDraw: function (config)
|
||||
{
|
||||
this.set2f('uOffset', x, 0);
|
||||
this.copySprite(target1, target2);
|
||||
var source = this.source;
|
||||
var target = this.target;
|
||||
|
||||
this.set2f('uOffset', 0, y);
|
||||
this.copySprite(target2, target1);
|
||||
}
|
||||
this.setShader(this.shaders[FX_CONST.SHADOW]);
|
||||
|
||||
this.blendFrames(target3, target1, target2, this.strength);
|
||||
this.set1i('samples', config.samples);
|
||||
this.set1f('intensity', config.intensity);
|
||||
this.set1f('decay', config.decay);
|
||||
this.set1f('power', config.power / config.samples);
|
||||
this.set2f('lightPosition', config.x, config.y);
|
||||
this.set4fv('color', config._color);
|
||||
|
||||
this.copyToGame(target2);
|
||||
}
|
||||
this.copy(source, target);
|
||||
|
||||
this.source = target;
|
||||
this.target = source;
|
||||
},
|
||||
|
||||
onPixelateDraw: function (config)
|
||||
{
|
||||
var source = this.source;
|
||||
var target = this.target;
|
||||
|
||||
this.setShader(this.shaders[FX_CONST.PIXELATE]);
|
||||
|
||||
this.set1f('amount', config.amount);
|
||||
this.set2f('resolution', source.width, source.height);
|
||||
|
||||
this.copy(source, target);
|
||||
|
||||
this.source = target;
|
||||
this.target = source;
|
||||
},
|
||||
|
||||
// onBloomDraw: function (target1, target2, target3)
|
||||
// {
|
||||
// this.manager.copyFrame(target1, target3);
|
||||
|
||||
// var x = (2 / target1.width) * this.offsetX;
|
||||
// var y = (2 / target1.height) * this.offsetY;
|
||||
|
||||
// for (var i = 0; i < this.steps; i++)
|
||||
// {
|
||||
// this.set2f('uOffset', x, 0);
|
||||
// this.copySprite(target1, target2);
|
||||
|
||||
// this.set2f('uOffset', 0, y);
|
||||
// this.copySprite(target2, target1);
|
||||
// }
|
||||
|
||||
// this.blendFrames(target3, target1, target2, this.strength);
|
||||
|
||||
// this.copyToGame(target2);
|
||||
// }
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -566,25 +566,22 @@ var PreFXPipeline = new Class({
|
|||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
},
|
||||
|
||||
// cls: function (target1, target2, target3)
|
||||
// {
|
||||
// var gl = this.gl;
|
||||
|
||||
// gl.clearColor(0, 0, 0, 0);
|
||||
// gl.viewport(0, 0, target1.width, target1.height);
|
||||
|
||||
// gl.bindFramebuffer(gl.FRAMEBUFFER, target1.framebuffer);
|
||||
// gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
// gl.bindFramebuffer(gl.FRAMEBUFFER, target2.framebuffer);
|
||||
// gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
// gl.bindFramebuffer(gl.FRAMEBUFFER, target3.framebuffer);
|
||||
// gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
// gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
// },
|
||||
|
||||
/**
|
||||
* Draws the `source` Render Target to the `target` Render Target.
|
||||
*
|
||||
* This is done using whatever the currently bound shader is. This method does
|
||||
* not set a shader. All it does is bind the source texture, set the viewport and UVs
|
||||
* then bind the target framebuffer, clears it and draws the source to it.
|
||||
*
|
||||
* At the end a null framebuffer is bound. No other clearing-up takes place, so
|
||||
* use this method carefully.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.Pipelines.PreFXPipeline#copy
|
||||
* @since 3.60.0
|
||||
*
|
||||
* @param {Phaser.Renderer.WebGL.RenderTarget} source - The source Render Target.
|
||||
* @param {Phaser.Renderer.WebGL.RenderTarget} target - The target Render Target.
|
||||
*/
|
||||
copy: function (source, target)
|
||||
{
|
||||
var gl = this.gl;
|
||||
|
|
|
@ -7,6 +7,7 @@ module.exports = [
|
|||
'',
|
||||
'varying vec2 outTexCoord;',
|
||||
'',
|
||||
'uniform float distance;',
|
||||
'uniform float outerStrength;',
|
||||
'uniform float innerStrength;',
|
||||
'uniform vec2 resolution;',
|
||||
|
@ -14,12 +15,8 @@ module.exports = [
|
|||
'uniform bool knockout;',
|
||||
'',
|
||||
'const float PI = 3.14159265358979323846264;',
|
||||
'',
|
||||
'const float DIST = __DIST__;',
|
||||
'const float SIZE = min(__SIZE__, PI * 2.0);',
|
||||
'const float NUM = ceil(PI * 2.0 / SIZE);',
|
||||
'',
|
||||
'const float MAX_TOTAL_ALPHA = NUM * DIST * (DIST + 1.0) / 2.0;',
|
||||
'const float MAX_DIST = 128.0;',
|
||||
'const float SIZE = 0.15;',
|
||||
'',
|
||||
'void main ()',
|
||||
'{',
|
||||
|
@ -34,24 +31,30 @@ module.exports = [
|
|||
' {',
|
||||
' direction = vec2(cos(angle), sin(angle)) * px;',
|
||||
'',
|
||||
' for (float curDistance = 0.0; curDistance < DIST; curDistance++)',
|
||||
' for (float curDistance = 0.0; curDistance < MAX_DIST; curDistance++)',
|
||||
' {',
|
||||
' if (curDistance >= distance)',
|
||||
' {',
|
||||
' break;',
|
||||
' }',
|
||||
'',
|
||||
' displaced = outTexCoord + direction * (curDistance + 1.0);',
|
||||
'',
|
||||
' totalAlpha += (DIST - curDistance) * texture2D(uMainSampler, displaced).a;',
|
||||
' totalAlpha += (distance - curDistance) * texture2D(uMainSampler, displaced).a;',
|
||||
' }',
|
||||
' }',
|
||||
'',
|
||||
' vec4 curColor = texture2D(uMainSampler, outTexCoord);',
|
||||
'',
|
||||
' float alphaRatio = (totalAlpha / MAX_TOTAL_ALPHA);',
|
||||
' float maxAlpha = 42.0 * distance * (distance + 1.0) / 2.0;',
|
||||
' float alphaRatio = (totalAlpha / maxAlpha);',
|
||||
'',
|
||||
' float innerGlowAlpha = (1.0 - alphaRatio) * innerStrength * curColor.a;',
|
||||
' float innerGlowStrength = min(1.0, innerGlowAlpha);',
|
||||
'',
|
||||
' vec4 innerColor = mix(curColor, glowColor, innerGlowStrength);',
|
||||
'',
|
||||
' float outerGlowAlpha = alphaRatio * outerStrength * (1. - curColor.a);',
|
||||
' float outerGlowAlpha = alphaRatio * outerStrength * (1.0 - curColor.a);',
|
||||
' float outerGlowStrength = min(1.0 - innerColor.a, outerGlowAlpha);',
|
||||
'',
|
||||
' vec4 outerGlowColor = outerGlowStrength * glowColor.rgba;',
|
||||
|
@ -59,6 +62,7 @@ module.exports = [
|
|||
' if (knockout)',
|
||||
' {',
|
||||
' float resultAlpha = outerGlowAlpha + innerGlowAlpha;',
|
||||
'',
|
||||
' gl_FragColor = vec4(glowColor.rgb * resultAlpha, resultAlpha);',
|
||||
' }',
|
||||
' else',
|
||||
|
|
33
src/renderer/webgl/shaders/FXPixelate-frag.js
Normal file
33
src/renderer/webgl/shaders/FXPixelate-frag.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
module.exports = [
|
||||
'#define SHADER_NAME PIXELATE_FS',
|
||||
'',
|
||||
'precision mediump float;',
|
||||
'',
|
||||
'uniform sampler2D uMainSampler;',
|
||||
'uniform vec2 resolution;',
|
||||
'uniform float amount;',
|
||||
'',
|
||||
'varying vec2 outTexCoord;',
|
||||
'',
|
||||
'void main ()',
|
||||
'{',
|
||||
' float pixelSize = floor(2.0 + amount);',
|
||||
'',
|
||||
' vec2 center = pixelSize * floor(outTexCoord * resolution / pixelSize) + pixelSize * vec2(0.5, 0.5);',
|
||||
'',
|
||||
' vec2 corner1 = center + pixelSize * vec2(-0.5, -0.5);',
|
||||
' vec2 corner2 = center + pixelSize * vec2(+0.5, -0.5);',
|
||||
' vec2 corner3 = center + pixelSize * vec2(+0.5, +0.5);',
|
||||
' vec2 corner4 = center + pixelSize * vec2(-0.5, +0.5);',
|
||||
'',
|
||||
' vec4 pixel = 0.4 * texture2D(uMainSampler, center / resolution);',
|
||||
'',
|
||||
' pixel += 0.15 * texture2D(uMainSampler, corner1 / resolution);',
|
||||
' pixel += 0.15 * texture2D(uMainSampler, corner2 / resolution);',
|
||||
' pixel += 0.15 * texture2D(uMainSampler, corner3 / resolution);',
|
||||
' pixel += 0.15 * texture2D(uMainSampler, corner4 / resolution);',
|
||||
'',
|
||||
' gl_FragColor = pixel;',
|
||||
'}',
|
||||
''
|
||||
].join('\n');
|
|
@ -4,15 +4,17 @@ module.exports = [
|
|||
'precision mediump float;',
|
||||
'',
|
||||
'uniform sampler2D uMainSampler;',
|
||||
'uniform vec2 lightPosition;',
|
||||
'uniform vec4 shadowColor;',
|
||||
'uniform float decay;',
|
||||
'uniform float power;',
|
||||
'uniform float intensity;',
|
||||
'',
|
||||
'varying vec2 outTexCoord;',
|
||||
'',
|
||||
'const int SAMPLES = __SAMPLES__;',
|
||||
'uniform vec2 lightPosition;',
|
||||
'uniform vec4 color;',
|
||||
'uniform float decay;',
|
||||
'uniform float power;',
|
||||
'uniform float intensity;',
|
||||
'uniform int samples;',
|
||||
'',
|
||||
'const int MAX = 12;',
|
||||
'',
|
||||
'void main ()',
|
||||
'{',
|
||||
|
@ -21,15 +23,21 @@ module.exports = [
|
|||
' vec2 pc = (lightPosition - outTexCoord) * intensity;',
|
||||
'',
|
||||
' float shadow = 0.0;',
|
||||
' float limit = max(float(MAX), float(samples));',
|
||||
'',
|
||||
' for (int i = 0; i < SAMPLES; ++i)',
|
||||
' for (int i = 0; i < MAX; ++i)',
|
||||
' {',
|
||||
' shadow += texture2D(uMainSampler, outTexCoord + float(i) * decay / float(SAMPLES) * pc).a * power;',
|
||||
' if (i >= samples)',
|
||||
' {',
|
||||
' break;',
|
||||
' }',
|
||||
'',
|
||||
' shadow += texture2D(uMainSampler, outTexCoord + float(i) * decay / limit * pc).a * power;',
|
||||
' }',
|
||||
'',
|
||||
' float mask = 1.0 - texture.a;',
|
||||
'',
|
||||
' gl_FragColor = mix(texture, shadowColor, shadow * mask);',
|
||||
' gl_FragColor = mix(texture, color, shadow * mask);',
|
||||
'}',
|
||||
''
|
||||
].join('\n');
|
||||
|
|
|
@ -6,6 +6,7 @@ uniform sampler2D uMainSampler;
|
|||
|
||||
varying vec2 outTexCoord;
|
||||
|
||||
uniform float distance;
|
||||
uniform float outerStrength;
|
||||
uniform float innerStrength;
|
||||
uniform vec2 resolution;
|
||||
|
@ -13,12 +14,8 @@ uniform vec4 glowColor;
|
|||
uniform bool knockout;
|
||||
|
||||
const float PI = 3.14159265358979323846264;
|
||||
|
||||
const float DIST = __DIST__;
|
||||
const float SIZE = min(__SIZE__, PI * 2.0);
|
||||
const float NUM = ceil(PI * 2.0 / SIZE);
|
||||
|
||||
const float MAX_TOTAL_ALPHA = NUM * DIST * (DIST + 1.0) / 2.0;
|
||||
const float MAX_DIST = 128.0;
|
||||
const float SIZE = 0.15;
|
||||
|
||||
void main ()
|
||||
{
|
||||
|
@ -33,24 +30,30 @@ void main ()
|
|||
{
|
||||
direction = vec2(cos(angle), sin(angle)) * px;
|
||||
|
||||
for (float curDistance = 0.0; curDistance < DIST; curDistance++)
|
||||
for (float curDistance = 0.0; curDistance < MAX_DIST; curDistance++)
|
||||
{
|
||||
if (curDistance >= distance)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
displaced = outTexCoord + direction * (curDistance + 1.0);
|
||||
|
||||
totalAlpha += (DIST - curDistance) * texture2D(uMainSampler, displaced).a;
|
||||
totalAlpha += (distance - curDistance) * texture2D(uMainSampler, displaced).a;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 curColor = texture2D(uMainSampler, outTexCoord);
|
||||
|
||||
float alphaRatio = (totalAlpha / MAX_TOTAL_ALPHA);
|
||||
float maxAlpha = 42.0 * distance * (distance + 1.0) / 2.0;
|
||||
float alphaRatio = (totalAlpha / maxAlpha);
|
||||
|
||||
float innerGlowAlpha = (1.0 - alphaRatio) * innerStrength * curColor.a;
|
||||
float innerGlowStrength = min(1.0, innerGlowAlpha);
|
||||
|
||||
vec4 innerColor = mix(curColor, glowColor, innerGlowStrength);
|
||||
|
||||
float outerGlowAlpha = alphaRatio * outerStrength * (1. - curColor.a);
|
||||
float outerGlowAlpha = alphaRatio * outerStrength * (1.0 - curColor.a);
|
||||
float outerGlowStrength = min(1.0 - innerColor.a, outerGlowAlpha);
|
||||
|
||||
vec4 outerGlowColor = outerGlowStrength * glowColor.rgba;
|
||||
|
@ -58,6 +61,7 @@ void main ()
|
|||
if (knockout)
|
||||
{
|
||||
float resultAlpha = outerGlowAlpha + innerGlowAlpha;
|
||||
|
||||
gl_FragColor = vec4(glowColor.rgb * resultAlpha, resultAlpha);
|
||||
}
|
||||
else
|
||||
|
|
30
src/renderer/webgl/shaders/src/FXPixelate.frag
Normal file
30
src/renderer/webgl/shaders/src/FXPixelate.frag
Normal file
|
@ -0,0 +1,30 @@
|
|||
#define SHADER_NAME PIXELATE_FS
|
||||
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D uMainSampler;
|
||||
uniform vec2 resolution;
|
||||
uniform float amount;
|
||||
|
||||
varying vec2 outTexCoord;
|
||||
|
||||
void main ()
|
||||
{
|
||||
float pixelSize = floor(2.0 + amount);
|
||||
|
||||
vec2 center = pixelSize * floor(outTexCoord * resolution / pixelSize) + pixelSize * vec2(0.5, 0.5);
|
||||
|
||||
vec2 corner1 = center + pixelSize * vec2(-0.5, -0.5);
|
||||
vec2 corner2 = center + pixelSize * vec2(+0.5, -0.5);
|
||||
vec2 corner3 = center + pixelSize * vec2(+0.5, +0.5);
|
||||
vec2 corner4 = center + pixelSize * vec2(-0.5, +0.5);
|
||||
|
||||
vec4 pixel = 0.4 * texture2D(uMainSampler, center / resolution);
|
||||
|
||||
pixel += 0.15 * texture2D(uMainSampler, corner1 / resolution);
|
||||
pixel += 0.15 * texture2D(uMainSampler, corner2 / resolution);
|
||||
pixel += 0.15 * texture2D(uMainSampler, corner3 / resolution);
|
||||
pixel += 0.15 * texture2D(uMainSampler, corner4 / resolution);
|
||||
|
||||
gl_FragColor = pixel;
|
||||
}
|
|
@ -3,15 +3,17 @@
|
|||
precision mediump float;
|
||||
|
||||
uniform sampler2D uMainSampler;
|
||||
uniform vec2 lightPosition;
|
||||
uniform vec4 shadowColor;
|
||||
uniform float decay;
|
||||
uniform float power;
|
||||
uniform float intensity;
|
||||
|
||||
varying vec2 outTexCoord;
|
||||
|
||||
const int SAMPLES = __SAMPLES__;
|
||||
uniform vec2 lightPosition;
|
||||
uniform vec4 color;
|
||||
uniform float decay;
|
||||
uniform float power;
|
||||
uniform float intensity;
|
||||
uniform int samples;
|
||||
|
||||
const int MAX = 12;
|
||||
|
||||
void main ()
|
||||
{
|
||||
|
@ -20,13 +22,19 @@ void main ()
|
|||
vec2 pc = (lightPosition - outTexCoord) * intensity;
|
||||
|
||||
float shadow = 0.0;
|
||||
float limit = max(float(MAX), float(samples));
|
||||
|
||||
for (int i = 0; i < SAMPLES; ++i)
|
||||
for (int i = 0; i < MAX; ++i)
|
||||
{
|
||||
shadow += texture2D(uMainSampler, outTexCoord + float(i) * decay / float(SAMPLES) * pc).a * power;
|
||||
if (i >= samples)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
shadow += texture2D(uMainSampler, outTexCoord + float(i) * decay / limit * pc).a * power;
|
||||
}
|
||||
|
||||
float mask = 1.0 - texture.a;
|
||||
|
||||
gl_FragColor = mix(texture, shadowColor, shadow * mask);
|
||||
gl_FragColor = mix(texture, color, shadow * mask);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue