mirror of
https://github.com/photonstorm/phaser
synced 2025-02-17 06:28:30 +00:00
Testing out a possible FX Pipeline
This commit is contained in:
parent
98ced9a38b
commit
963ff647e6
12 changed files with 497 additions and 122 deletions
|
@ -4,8 +4,6 @@
|
|||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Bloom = require('../../renderer/webgl/pipelines/fx/Bloom.js');
|
||||
|
||||
/**
|
||||
* Provides methods used for setting the FX values of a Game Object.
|
||||
* Should be applied as a mixin and not used directly.
|
||||
|
@ -17,6 +15,8 @@ var Bloom = require('../../renderer/webgl/pipelines/fx/Bloom.js');
|
|||
|
||||
var FX = {
|
||||
|
||||
fx: null,
|
||||
|
||||
/**
|
||||
* The amount of extra padding to be applied to this Game Object
|
||||
* when it is being rendered by a PreFX or SpriteFX Pipeline.
|
||||
|
@ -93,18 +93,50 @@ var FX = {
|
|||
{
|
||||
},
|
||||
|
||||
enableFX: function ()
|
||||
{
|
||||
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)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var pipeline;
|
||||
var pipelines = renderer.pipelines;
|
||||
|
||||
if (pipelines)
|
||||
{
|
||||
pipeline = pipelines.FX_PIPELINE;
|
||||
}
|
||||
|
||||
this.pipeline = pipeline;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addBloom: function (r, g, b)
|
||||
{
|
||||
var instance = new Bloom(this.scene.sys.game);
|
||||
|
||||
instance.gameObject = this;
|
||||
instance.setColor(r, g, b);
|
||||
|
||||
this.postPipelines.push(instance);
|
||||
|
||||
this.hasPostPipeline = true;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@ var SnapCeil = require('../../math/snap/SnapCeil');
|
|||
|
||||
// Default Phaser 3 Pipelines
|
||||
var BitmapMaskPipeline = require('./pipelines/BitmapMaskPipeline');
|
||||
var FXPipeline = require('./pipelines/FXPipeline');
|
||||
var LightPipeline = require('./pipelines/LightPipeline');
|
||||
var MobilePipeline = require('./pipelines/MobilePipeline');
|
||||
var MultiPipeline = require('./pipelines/MultiPipeline');
|
||||
|
@ -30,7 +31,7 @@ var UtilityPipeline = require('./pipelines/UtilityPipeline');
|
|||
* The `WebGLRenderer` owns a single instance of the Pipeline Manager, which you can access
|
||||
* via the `WebGLRenderer.pipelines` property.
|
||||
*
|
||||
* By default, there are 7 pipelines installed into the Pipeline Manager when Phaser boots:
|
||||
* By default, there are 9 pipelines installed into the Pipeline Manager when Phaser boots:
|
||||
*
|
||||
* 1. The Multi Pipeline. Responsible for all multi-texture rendering, i.e. Sprites and Tilemaps.
|
||||
* 2. The Rope Pipeline. Responsible for rendering the Rope Game Object.
|
||||
|
@ -40,6 +41,7 @@ var UtilityPipeline = require('./pipelines/UtilityPipeline');
|
|||
* 6. The Bitmap Mask Pipeline. Responsible for Bitmap Mask rendering.
|
||||
* 7. The Utility Pipeline. Responsible for providing lots of handy texture manipulation functions.
|
||||
* 8. The Mobile Pipeline. Responsible for rendering on mobile with single-bound textures.
|
||||
* 9. The FX Pipeline. Responsible for rendering Game Objects with special FX applied to them.
|
||||
*
|
||||
* You can add your own custom pipeline via the `PipelineManager.add` method. Pipelines are
|
||||
* identified by unique string-based keys.
|
||||
|
@ -92,7 +94,8 @@ var PipelineManager = new Class({
|
|||
[ CONST.ROPE_PIPELINE, RopePipeline ],
|
||||
[ CONST.LIGHT_PIPELINE, LightPipeline ],
|
||||
[ CONST.POINTLIGHT_PIPELINE, PointLightPipeline ],
|
||||
[ CONST.MOBILE_PIPELINE, MobilePipeline ]
|
||||
[ CONST.MOBILE_PIPELINE, MobilePipeline ],
|
||||
[ CONST.FX_PIPELINE, FXPipeline ]
|
||||
]);
|
||||
|
||||
/**
|
||||
|
@ -186,7 +189,7 @@ var PipelineManager = new Class({
|
|||
/**
|
||||
* A constant-style reference to the Mobile Pipeline Instance.
|
||||
*
|
||||
* This is the default Phaser 3 pipeline and is used by the WebGL Renderer to manage
|
||||
* This is the default Phaser 3 mobile pipeline and is used by the WebGL Renderer to manage
|
||||
* camera effects and more on mobile devices. This property is set during the `boot` method.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.PipelineManager#MOBILE_PIPELINE
|
||||
|
@ -196,6 +199,19 @@ var PipelineManager = new Class({
|
|||
*/
|
||||
this.MOBILE_PIPELINE = null;
|
||||
|
||||
/**
|
||||
* A constant-style reference to the FX Pipeline Instance.
|
||||
*
|
||||
* This is the default Phaser 3 FX pipeline and is used by the WebGL Renderer to manage
|
||||
* Game Objects with special effects enabled. This property is set during the `boot` method.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.PipelineManager#FX_PIPELINE
|
||||
* @type {Phaser.Renderer.WebGL.Pipelines.FXPipeline}
|
||||
* @default null
|
||||
* @since 3.60.0
|
||||
*/
|
||||
this.FX_PIPELINE = null;
|
||||
|
||||
/**
|
||||
* A reference to the Full Frame 1 Render Target that belongs to the
|
||||
* Utility Pipeline. This property is set during the `boot` method.
|
||||
|
@ -378,6 +394,7 @@ var PipelineManager = new Class({
|
|||
this.MULTI_PIPELINE = this.get(CONST.MULTI_PIPELINE);
|
||||
this.BITMAPMASK_PIPELINE = this.get(CONST.BITMAPMASK_PIPELINE);
|
||||
this.MOBILE_PIPELINE = this.get(CONST.MOBILE_PIPELINE);
|
||||
this.FX_PIPELINE = this.get(CONST.FX_PIPELINE);
|
||||
|
||||
// And now the ones in the config, if any
|
||||
|
||||
|
@ -1146,6 +1163,19 @@ var PipelineManager = new Class({
|
|||
return this.UTILITY_PIPELINE.bind(currentShader);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the FX Pipeline to be the currently bound pipeline.
|
||||
*
|
||||
* @method Phaser.Renderer.WebGL.PipelineManager#setFX
|
||||
* @since 3.60.0
|
||||
*
|
||||
* @return {Phaser.Renderer.WebGL.Pipelines.FXPipeline} The FX Pipeline instance.
|
||||
*/
|
||||
setFX: function ()
|
||||
{
|
||||
return this.set(this.FX_PIPELINE);
|
||||
},
|
||||
|
||||
/**
|
||||
* Use this to reset the gl context to the state that Phaser requires to continue rendering.
|
||||
*
|
||||
|
|
145
src/renderer/webgl/pipelines/FXPipeline.js
Normal file
145
src/renderer/webgl/pipelines/FXPipeline.js
Normal file
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* @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 PreFXPipeline = require('./PreFXPipeline');
|
||||
var BloomFrag = require('../shaders/FXBloom-frag.js');
|
||||
var GlowFrag = require('../shaders/FXGlow-frag.js');
|
||||
var ShadowFrag = require('../shaders/FXShadow-frag.js');
|
||||
var SingleQuadVS = require('../shaders/Single-vert.js');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
*
|
||||
* @class FX
|
||||
* @extends Phaser.Renderer.WebGL.Pipelines.PreFXPipeline
|
||||
* @memberof Phaser.Renderer.WebGL.Pipelines
|
||||
* @constructor
|
||||
* @since 3.60.0
|
||||
*
|
||||
* @param {Phaser.Game} game - A reference to the Phaser game instance.
|
||||
*/
|
||||
var FXPipeline = new Class({
|
||||
|
||||
Extends: PreFXPipeline,
|
||||
|
||||
initialize:
|
||||
|
||||
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;
|
||||
|
||||
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 ]
|
||||
};
|
||||
},
|
||||
|
||||
boot: function ()
|
||||
{
|
||||
PreFXPipeline.prototype.boot.call(this);
|
||||
|
||||
console.log(this.shaders);
|
||||
|
||||
},
|
||||
|
||||
onDraw: function (target1, target2, target3)
|
||||
{
|
||||
// tempSprite = current sprite being drawn
|
||||
|
||||
this.setShader(this.shaders[4]);
|
||||
|
||||
var glow = this.tempSprite.fx.glow;
|
||||
|
||||
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);
|
||||
|
||||
this.copy(target1, target2);
|
||||
|
||||
this.setShader(this.shaders[5]);
|
||||
|
||||
var shadow = this.tempSprite.fx.shadow;
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = FXPipeline;
|
|
@ -566,6 +566,51 @@ 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);
|
||||
// },
|
||||
|
||||
copy: function (source, target)
|
||||
{
|
||||
var gl = this.gl;
|
||||
|
||||
this.set1i('uMainSampler', 0);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, source.texture);
|
||||
|
||||
// source and target must always be the same size
|
||||
gl.viewport(0, 0, source.width, source.height);
|
||||
|
||||
this.setUVs(0, 0, 0, 1, 1, 1, 1, 0);
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, target.framebuffer);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target.texture, 0);
|
||||
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
gl.bufferData(gl.ARRAY_BUFFER, this.quadVertexData, gl.STATIC_DRAW);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draws the `source1` and `source2` Render Targets to the `target` Render Target
|
||||
* using a linear blend effect, which is controlled by the `strength` parameter.
|
||||
|
@ -713,15 +758,23 @@ var PreFXPipeline = new Class({
|
|||
// var y2 = matrix.getY(xw, y);
|
||||
// var y3 = matrix.getY(xw, yh);
|
||||
|
||||
this.batchVert(x0, y0, 0, 0, 0, 0, 0xffffff);
|
||||
this.batchVert(x1, y1, 0, 1, 0, 0, 0xffffff);
|
||||
this.batchVert(x2, y2, 1, 1, 0, 0, 0xffffff);
|
||||
this.batchVert(x0, y0, 0, 0, 0, 0, 0xffffff);
|
||||
this.batchVert(x2, y2, 1, 1, 0, 0, 0xffffff);
|
||||
this.batchVert(x3, y3, 1, 0, 0, 0, 0xffffff);
|
||||
var white = 0xffffff;
|
||||
|
||||
this.batchVert(x0, y0, 0, 0, 0, 0, white);
|
||||
this.batchVert(x1, y1, 0, 1, 0, 0, white);
|
||||
this.batchVert(x2, y2, 1, 1, 0, 0, white);
|
||||
this.batchVert(x0, y0, 0, 0, 0, 0, white);
|
||||
this.batchVert(x2, y2, 1, 1, 0, 0, white);
|
||||
this.batchVert(x3, y3, 1, 0, 0, 0, white);
|
||||
|
||||
this.flush();
|
||||
|
||||
// Clear the source framebuffer out, ready for the next pass
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, source.framebuffer);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
|
||||
// No hanging references
|
||||
this.tempSprite = null;
|
||||
},
|
||||
|
|
|
@ -104,7 +104,17 @@ var PIPELINE_CONST = {
|
|||
* @const
|
||||
* @since 3.60.0
|
||||
*/
|
||||
MOBILE_PIPELINE: 'MobilePipeline'
|
||||
MOBILE_PIPELINE: 'MobilePipeline',
|
||||
|
||||
/**
|
||||
* The Special FX Pipeline.
|
||||
*
|
||||
* @name Phaser.Renderer.WebGL.Pipelines.FX_PIPELINE
|
||||
* @type {string}
|
||||
* @const
|
||||
* @since 3.60.0
|
||||
*/
|
||||
FX_PIPELINE: 'FxPipeline'
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/**
|
||||
* @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 SpriteFXPipeline = require('../SpriteFXPipeline');
|
||||
var BloomFrag = require('../../shaders/FXBloom-frag.js');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
*
|
||||
* @class Bloom
|
||||
* @extends Phaser.Renderer.WebGL.Pipelines.SpriteFXPipeline
|
||||
* @memberof Phaser.Renderer.WebGL.Pipelines.FX
|
||||
* @constructor
|
||||
* @since 3.60.0
|
||||
*
|
||||
* @param {Phaser.Game} game - A reference to the Phaser game instance.
|
||||
*/
|
||||
var Bloom = new Class({
|
||||
|
||||
Extends: SpriteFXPipeline,
|
||||
|
||||
initialize:
|
||||
|
||||
function Bloom (game)
|
||||
{
|
||||
console.log('bloom', game);
|
||||
|
||||
SpriteFXPipeline.call(this, {
|
||||
game: game,
|
||||
fragShader: BloomFrag
|
||||
});
|
||||
|
||||
this.steps = 4;
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
this.blurStrength = 1;
|
||||
this.strength = 1;
|
||||
this.color = [ 1, 1, 1 ];
|
||||
},
|
||||
|
||||
onPreRender: function ()
|
||||
{
|
||||
this.set1f('uStrength', this.blurStrength);
|
||||
this.set3fv('uColor', this.color);
|
||||
},
|
||||
|
||||
onDraw: 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);
|
||||
},
|
||||
|
||||
setColor: function (r, g, b)
|
||||
{
|
||||
this.color[0] = r;
|
||||
this.color[1] = g;
|
||||
this.color[2] = b;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = Bloom;
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2013-2023 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @namespace Phaser.Renderer.WebGL.Pipelines.FX
|
||||
*/
|
||||
|
||||
var FX = {
|
||||
|
||||
Bloom: require('./Bloom')
|
||||
|
||||
};
|
||||
|
||||
module.exports = FX;
|
|
@ -15,6 +15,7 @@ var Pipelines = {
|
|||
|
||||
BitmapMaskPipeline: require('./BitmapMaskPipeline'),
|
||||
Events: require('./events'),
|
||||
FXPipeline: require('./FXPipeline'),
|
||||
LightPipeline: require('./LightPipeline'),
|
||||
MobilePipeline: require('./MobilePipeline'),
|
||||
MultiPipeline: require('./MultiPipeline'),
|
||||
|
|
70
src/renderer/webgl/shaders/FXGlow-frag.js
Normal file
70
src/renderer/webgl/shaders/FXGlow-frag.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
module.exports = [
|
||||
'#define SHADER_NAME GLOW_FS',
|
||||
'',
|
||||
'precision mediump float;',
|
||||
'',
|
||||
'uniform sampler2D uMainSampler;',
|
||||
'',
|
||||
'varying vec2 outTexCoord;',
|
||||
'',
|
||||
'uniform float outerStrength;',
|
||||
'uniform float innerStrength;',
|
||||
'uniform vec2 resolution;',
|
||||
'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;',
|
||||
'',
|
||||
'void main ()',
|
||||
'{',
|
||||
' vec2 px = vec2(1.0 / resolution.x, 1.0 / resolution.y);',
|
||||
'',
|
||||
' float totalAlpha = 0.0;',
|
||||
'',
|
||||
' vec2 direction;',
|
||||
' vec2 displaced;',
|
||||
'',
|
||||
' for (float angle = 0.0; angle < PI * 2.0; angle += SIZE)',
|
||||
' {',
|
||||
' direction = vec2(cos(angle), sin(angle)) * px;',
|
||||
'',
|
||||
' for (float curDistance = 0.0; curDistance < DIST; curDistance++)',
|
||||
' {',
|
||||
' displaced = outTexCoord + direction * (curDistance + 1.0);',
|
||||
'',
|
||||
' totalAlpha += (DIST - curDistance) * texture2D(uMainSampler, displaced).a;',
|
||||
' }',
|
||||
' }',
|
||||
'',
|
||||
' vec4 curColor = texture2D(uMainSampler, outTexCoord);',
|
||||
'',
|
||||
' float alphaRatio = (totalAlpha / MAX_TOTAL_ALPHA);',
|
||||
'',
|
||||
' 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 outerGlowStrength = min(1.0 - innerColor.a, outerGlowAlpha);',
|
||||
'',
|
||||
' vec4 outerGlowColor = outerGlowStrength * glowColor.rgba;',
|
||||
'',
|
||||
' if (knockout)',
|
||||
' {',
|
||||
' float resultAlpha = outerGlowAlpha + innerGlowAlpha;',
|
||||
' gl_FragColor = vec4(glowColor.rgb * resultAlpha, resultAlpha);',
|
||||
' }',
|
||||
' else',
|
||||
' {',
|
||||
' gl_FragColor = innerColor + outerGlowColor;',
|
||||
' }',
|
||||
'}',
|
||||
''
|
||||
].join('\n');
|
35
src/renderer/webgl/shaders/FXShadow-frag.js
Normal file
35
src/renderer/webgl/shaders/FXShadow-frag.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
module.exports = [
|
||||
'#define SHADER_NAME SHADOW_FS',
|
||||
'',
|
||||
'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__;',
|
||||
'',
|
||||
'void main ()',
|
||||
'{',
|
||||
' vec4 texture = texture2D(uMainSampler, outTexCoord);',
|
||||
'',
|
||||
' vec2 pc = (lightPosition - outTexCoord) * intensity;',
|
||||
'',
|
||||
' float shadow = 0.0;',
|
||||
'',
|
||||
' for (int i = 0; i < SAMPLES; ++i)',
|
||||
' {',
|
||||
' shadow += texture2D(uMainSampler, outTexCoord + float(i) * decay / float(SAMPLES) * pc).a * power;',
|
||||
' }',
|
||||
'',
|
||||
' float mask = 1.0 - texture.a;',
|
||||
'',
|
||||
' gl_FragColor = mix(texture, shadowColor, shadow * mask);',
|
||||
'}',
|
||||
''
|
||||
].join('\n');
|
67
src/renderer/webgl/shaders/src/FXGlow.frag
Normal file
67
src/renderer/webgl/shaders/src/FXGlow.frag
Normal file
|
@ -0,0 +1,67 @@
|
|||
#define SHADER_NAME GLOW_FS
|
||||
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D uMainSampler;
|
||||
|
||||
varying vec2 outTexCoord;
|
||||
|
||||
uniform float outerStrength;
|
||||
uniform float innerStrength;
|
||||
uniform vec2 resolution;
|
||||
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;
|
||||
|
||||
void main ()
|
||||
{
|
||||
vec2 px = vec2(1.0 / resolution.x, 1.0 / resolution.y);
|
||||
|
||||
float totalAlpha = 0.0;
|
||||
|
||||
vec2 direction;
|
||||
vec2 displaced;
|
||||
|
||||
for (float angle = 0.0; angle < PI * 2.0; angle += SIZE)
|
||||
{
|
||||
direction = vec2(cos(angle), sin(angle)) * px;
|
||||
|
||||
for (float curDistance = 0.0; curDistance < DIST; curDistance++)
|
||||
{
|
||||
displaced = outTexCoord + direction * (curDistance + 1.0);
|
||||
|
||||
totalAlpha += (DIST - curDistance) * texture2D(uMainSampler, displaced).a;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 curColor = texture2D(uMainSampler, outTexCoord);
|
||||
|
||||
float alphaRatio = (totalAlpha / MAX_TOTAL_ALPHA);
|
||||
|
||||
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 outerGlowStrength = min(1.0 - innerColor.a, outerGlowAlpha);
|
||||
|
||||
vec4 outerGlowColor = outerGlowStrength * glowColor.rgba;
|
||||
|
||||
if (knockout)
|
||||
{
|
||||
float resultAlpha = outerGlowAlpha + innerGlowAlpha;
|
||||
gl_FragColor = vec4(glowColor.rgb * resultAlpha, resultAlpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_FragColor = innerColor + outerGlowColor;
|
||||
}
|
||||
}
|
32
src/renderer/webgl/shaders/src/FXShadow.frag
Normal file
32
src/renderer/webgl/shaders/src/FXShadow.frag
Normal file
|
@ -0,0 +1,32 @@
|
|||
#define SHADER_NAME SHADOW_FS
|
||||
|
||||
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__;
|
||||
|
||||
void main ()
|
||||
{
|
||||
vec4 texture = texture2D(uMainSampler, outTexCoord);
|
||||
|
||||
vec2 pc = (lightPosition - outTexCoord) * intensity;
|
||||
|
||||
float shadow = 0.0;
|
||||
|
||||
for (int i = 0; i < SAMPLES; ++i)
|
||||
{
|
||||
shadow += texture2D(uMainSampler, outTexCoord + float(i) * decay / float(SAMPLES) * pc).a * power;
|
||||
}
|
||||
|
||||
float mask = 1.0 - texture.a;
|
||||
|
||||
gl_FragColor = mix(texture, shadowColor, shadow * mask);
|
||||
}
|
Loading…
Add table
Reference in a new issue